Harding
October 23, 2025, 10:59am
1
According to The official Python docs
The prototype for save_database is:
def save_database(outfile: str=None, flags: int=-1, root: 'snapshot_t'=None,
attr: 'snapshot_t'=None) ->bool:
"""Save current database using a new file name.
:param outfile: output database file name; nullptr means the current path
:param flags: Database flags; -1 means the current flags
:param root: optional: snapshot tree root.
:param attr: optional: snapshot attributes
:returns: success"""
return _ida_loader.save_database(outfile, flags, root, attr)
However, one cannot call it:
TypeError Traceback (most recent call last)
Cell In[7], line 1
----> 1 ida_loader.save_database()
File <retracted>\ida_loader.py:715, in save_database(outfile, flags, root, attr)
706 def save_database(outfile: str=None, flags: int=-1, root: 'snapshot_t'=None,
707 attr: 'snapshot_t'=None) ->bool:
708 """Save current database using a new file name.
709
710 :param outfile: output database file name; nullptr means the current path
(...)
713 :param attr: optional: snapshot attributes
714 :returns: success"""
--> 715 return _ida_loader.save_database(outfile, flags, root, attr)
TypeError: Wrong number or type of arguments for overloaded function 'save_database'.
Possible C/C++ prototypes are:
save_database(char const *,uint32,snapshot_t const *,snapshot_t const *)
save_database(char const *,uint32,snapshot_t const *)
save_database(char const *,uint32)
save_database(char const *)
save_database()
The second argument is not int, it is uint32
Hi, thanks for the report! We’ll check why these calls aren’t working and follow up once we have more updates.
Hi @Harding ,
Indeed, the save_database() and save_database(char const *) are both unusable due to negative default value. One of these C++ vs Python inconsistencies that fell through the cracks.
Let me fix this upstream and make it available with the next release.
Until then, if you need the equivalent of idaapi.save_database(), you can use the following line:
idaapi.save_database(idaapi.get_path(idaapi.PATH_TYPE_IDB), 0)
Harding
October 27, 2025, 10:13am
4
Good you get it fixed. I have already made a “fix” for it by using ida_idaapi.as_uint32 as you can see here:
@param arg_snapshot_attribute: optional, snapshot attributes
@return success
'''
# TODO: Check how this plays with ida_domain
# TODO: How does this work with the flags? Like compressiong and so on? Should the user be able to set that in this function?
l_new_filename = arg_new_filename or None
l_my_extension = _os.path.splitext(input_file.idb_path)[1]
if l_new_filename and not l_new_filename.endswith(l_my_extension):
l_new_filename += l_my_extension
return _ida_loader.save_database(outfile=l_new_filename, flags=_ida_idaapi.as_uint32(arg_database_flags), root=arg_snapshot_root, attr=arg_snapshot_attribute)
@validate_call(config={"arbitrary_types_allowed": True, "strict": True, "validate_return": True})
def ida_exit(arg_exit_code: int = 0,
arg_save_database: bool = True,
arg_compress_database: bool = True,
arg_collect_garbage: bool = True) -> None:
''' Exit IDA and optionally save the IDB
A good use for this function is as the last call in a script run in batch mode.
See links() for more info about batch mode
1 Like
Nice, I see!
My fix changes the default to 0 instead of -1, but the functionality stays the same. Glad you found a way to work around.
1 Like
Harding
February 27, 2026, 7:12pm
6
Sorry to necro this thread but the save_database still works kinda wonkly.
If calling it with an empty string
ida_loader.save_database("")
I get the following unreadable popup:
And if I click the X in the top right corner the function returns True and I get the log line:
Leaving database unpacked and packed copy in .$$$ and there is a file created named .$$$ in the working dir.
Hi @Harding ,
Reports are always welcome, there’s no such thing as “necro-ing” the thread here.
The first parameter of save_database() is outfile, which can represent the name of the new database file, or the current database in case outfile is None (or nullptr in C++). Passing an empty string fails because "” will be interpreted as a file name.
We could catch that earlier and show a better error explanation. Would that work for you as the expected outcome, or do you have a particular reason for passing an empty string?
The short answer is that I have a wrapper around it and I have the type str and used the empty string to signal the same as you do with a nullptr. That’s how I found the error and even if I can change it (I added a check as you can see here: community_base/community_base.py at b5f727c122b1b520c68e01bd8f6793d2c7ce5064 · Harding-Stardust/community_base · GitHub ) but I wanted to let the empty string fall through.
So the bug is minor and it was just a strange error message that also created an unwanted file that I wanted to report. You can use None or empty string as the signal to “use the normal IDB path”, it doesn’t really matter.
1 Like