# PyErr Desk > Audit a Python module's error handling and resource cleanup before it runs unattended - where does every error go, and what is left open when something raises - then harden it. The free check runs in the browser and uploads nothing: it lexes pasted Python (one or more files), rebuilds the block structure, matches every except to its try, inventories every except block and what its handler does, every raise, every exception class and every file, connection, socket, session, client, pool or temporary file with how it is released, and runs 20 deterministic checks drawn from Python error-handling and resource-management practice. The paid audit rates exceptions, validation, partial failure and resources, confirms or dismisses every flag and gives exact before/after edits per finding; the paid harden lane writes the whole hardened file(s), the list of changes and an exception catalogue. The page checks every quote and line against the paste, applies every edit and file back into the paste and re-runs its checks, and calls out a reply that repeats a credential from the paste. App: https://pyerr-desk.skillsafe.ai/ API tutorial: https://pyerr-desk.skillsafe.ai/api.html ## Input - The code pasted into one box, each file introduced by a `# file: ` line; dropped files or a dropped package folder are joined that way automatically. A paste with no `# file:` line is read as one file (app.py). - Nothing is imported or run: every flag is a reading of the text, with the file and line it points at. Strings and comments are lexed out first, so a string that mentions `except:` or `open(` is never a finding. - How callers handle these errors, and what a framework does with one that escapes, is outside the paste (PE-21 says so); the paid lanes ask rather than assume. ## Flags the free check raises - PE-01 (medium): a bare except or except BaseException that does not re-raise - it also traps KeyboardInterrupt and SystemExit. - PE-02 (high): a broad except that swallows every error - nothing logged, re-raised or recorded. - PE-03 (medium): a broad except that logs without the traceback and does not re-raise. - PE-04 (low): a specific exception ignored with pass and no comment saying why. - PE-05 (high under a broad except, medium under a specific one): a failed item dropped silently inside a batch loop. - PE-06 (medium): a broad except that turns every failure into a normal-looking return value (None, False, -1, {}). - PE-07 (low): an exception translated inside an except without `from`, or re-raised as `raise err`. - PE-08 (medium): `raise Exception(...)` - the generic base class. - PE-09 (low): a built-in exception raised with no message, or a one- or two-word one. - PE-10 (medium): assert used to validate a function's arguments (removed by python -O); test files are exempt. - PE-11 (low): a broad try block around twelve or more statements. - PE-12 (medium): a custom exception derived from BaseException. - PE-13 (medium): a file, connection, socket, session, client, pool or temporary file opened in a function without a with block and never closed. - PE-14 (medium): a resource closed only on the success path (close() not in a finally or with). - PE-15 (high): `__exit__` that returns True unconditionally - every exception in the block is suppressed. - PE-16 (medium): a @contextmanager whose yield is not inside try/finally - the cleanup after it is skipped when the block raises. - PE-17 (high): return, break or continue inside finally - an exception in flight is discarded. - PE-18 (medium): commit() with no rollback when a write before it fails. - PE-19 (low): a string built with += in a loop. - PE-20 (low): __del__ used to release resources. - PE-21 (info): context - files, functions, except blocks and resources read. ## Free extras - Every except block with what it catches, what its handler does, whether the traceback is kept and whether it is in a loop; every resource with its call, kind, name and how it is released; every raise; every exception class with its base. - Put any audit finding (or all of them, or the hardened files) back into the paste and re-run the check; undo puts the original back. - Exports: the check as Markdown, the flags as CSV, the edited or hardened code, the findings or changes as CSV, the whole result as JSON. ## Paid lanes (the `task` field) - `audit`: `{task, verdict: blocked|needs_work|ready, headline, module, areas: [{area: exceptions|validation|partial_failure|resources, status: good|partial|poor|n_a, note}], findings: [{id, flags, file, line, severity, area, title, evidence, why, edits: [{before, after}]}], flag_answers: [{flag, status: confirmed|dismissed, reason}], plan, questions, summary}`. `before` is an exact slice of the file, applied in order. - `harden`: `{task, verdict: hardened|partial, headline, files: [{path, content}], exceptions: [{name, base, raised_in, why}], changes: [{area, where, what}], open: [{item, reason}], questions, summary}`. `content` is the whole file; every function keeps its arguments in order. - Run input: `{task, code, facts, note?, audit_handoff?, retry_note?}` - all strings; `facts` is the page's analysis as a JSON string. The audit hands its findings to the harden lane with every edit applied to `code`. - Model: gpt-terra, 10% publisher markup. A run needs a signed-in account; the reservation shown before a run is a hold, and only what the run uses is charged. ## Sources - python-error-handling by Seth Hobson, wshobson/agents (github.com/wshobson/agents, plugins/python-development/skills/python-error-handling), MIT - https://skillsafe.ai/skill/@wshobson/python-error-handling - python-resource-management by Seth Hobson, wshobson/agents (github.com/wshobson/agents, plugins/python-development/skills/python-resource-management), MIT - https://skillsafe.ai/skill/@wshobson/python-resource-management - The checks and the reconciliation are original to this app.