Skip to content

[BUG] CRITICAL LookupError: unknown error handler name 'reversible' during hash cracking on Windows (multiprocessing spawn) #6143

Closed

Description

@Scj752

Environment

  • sqlmap version: 1.10.10 (installed via pip; banner shows 1.10.10#pip)
  • Python: 3.10.11 (MSC v.1929 64 bit, AMD64)
  • OS: Windows 11 (build 10.0.26200)
  • Installation method: pip install sqlmap (official PyPI wheel)
  • Target: vulnerables/web-dvwa docker image, MariaDB (unrelated to the bug)

Command

sqlmap -u "http://localhost:8080/vulnerabilities/sqli/?id=1&Submit=Submit" \
       --cookie="PHPSESSID=xxxx; security=low" --batch -D dvwa -T users --dump

Description

While dumping a table that contains MD5 password hashes, sqlmap automatically starts
dictionary-based cracking in 16 parallel processes. On Windows, every worker emits a
CRITICAL log for each dictionary entry it processes:

[CRITICAL] there was a problem while hashing entry: 'abc123' ('LookupError: unknown error handler name 'reversible''). Please report by e-mail to 'dev@sqlmap.org'
[CRITICAL] there was a problem while hashing entry: 'charley' ('LookupError: unknown error handler name 'reversible'') ...
[CRITICAL] there was a problem while hashing entry: 'letmein' ('LookupError: unknown error handler name 'reversible'') ...
[CRITICAL] there was a problem while hashing entry: 'password' ('LookupError: unknown error handler name 'reversible'') ...

The dump and the cracking itself still complete correctly (plaintexts are recovered), so this is
non-fatal, but the CRITICAL messages are misleading (they suggest a total failure when in fact
the data and even the cracked hashes are returned).

Root cause (analysis)

lib/core/patch.py (around lines 140-147) registers a custom codec error handler:

codecs.register_error("reversible", _reversible)

This registration happens once, inside dirtyPatches(), in the main process at startup.
The password-cracking code uses multiprocessing. On Windows, the spawn start method creates
brand-new interpreter processes that do not re-execute dirtyPatches(), so the "reversible"
error handler is not registered in the workers. When a worker calls getUnicode() / openFile()
with errors="reversible" (e.g. lib/core/convert.py:581 and lib/core/common.py:4022),
Python raises:

LookupError: unknown error handler name 'reversible'

On Linux, multiprocessing uses fork, so workers inherit the already-registered handler and the
bug does not appear. It is therefore Windows-specific.

Possibly related: #6122 (a similar worker-side patch/attribute error during hash cracking on
Windows, but a different exception).

Suggested fix

  • Register the "reversible" codec error handler in the multiprocessing worker initializer
    (call codecs.register_error in the child init function), or
  • Ensure dirtyPatches() is executed at worker startup / module import so the handler exists in
    spawned children, or
  • Guard the registration so it is re-applied when children are spawned.

Workaround

  • Run with --answers="crack=n" to skip cracking (no CRITICAL spam), or
  • Run sqlmap on Linux / WSL (fork), where the issue does not occur.

Activity

  1. Scj752 commented on Oct 11, 2026

    @Scj752
    Author

    Minimal reproducer (confirms the root cause)

    Environment: Windows 11, Python 3.10.11, sqlmap 1.10.10. The default multiprocessing start method on Windows is spawn.

    reversible_repro.py:

    import codecs
    import multiprocessing as mp
    
    
    def _reversible(ex):
        # Same shape as sqlmap's handler in lib/core/patch.py
        return (u"", ex.end)
    
    
    def check(_):
        try:
            codecs.lookup_error("reversible")
            return "OK: 'reversible' handler found"
        except LookupError as e:
            return "FAIL: LookupError: %s" % e
    
    
    if __name__ == "__main__":
        # sqlmap registers this once in the main process via dirtyPatches()
        codecs.register_error("reversible", _reversible)
    
        print("start method :", mp.get_start_method())
        print("Main process :", check(None))
    
        with mp.Pool(2) as pool:
            print("Worker procs :", pool.map(check, [0, 1]))

    Output on Windows:

    start method : spawn
    Main process : OK: 'reversible' handler found
    Worker procs : ["FAIL: LookupError: unknown error handler name 'reversible'", "FAIL: LookupError: unknown error handler name 'reversible'"]
    

    Conclusion

    codecs.register_error("reversible", ...) is called only in the main process (as dirtyPatches() does at startup). Because Windows multiprocessing uses spawn, the child worker processes start fresh and never re-run that registration, so the hash-cracking workers raise:

    LookupError: unknown error handler name 'reversible'
    

    On Linux, fork makes workers inherit the registration, which is why the bug is Windows-specific.

    Suggested fix

    Register the "reversible" codec error handler inside the multiprocessing worker initializer (or otherwise ensure dirtyPatches() is executed at worker startup), so spawned children have the handler registered.

    Note

    The bug is non-fatal: the dump and the hash cracking still complete (plaintexts are recovered); only the misleading [CRITICAL] messages are emitted per dictionary entry.

  2. self-assigned this
    on Oct 11, 2026
  3. stamparm commented on Oct 11, 2026

    @stamparm
    Member

    thank you for excellent report

  4. added a commit that references this issue on Oct 12, 2026
    5b18053
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions