{"record":{"id":"1d340ee918648633","repo":"OtterMind/Chat2DB","slug":"prepared-qq-notification-is-not-valid-json","errorCode":null,"errorMessage":"Prepared QQ notification is not valid JSON","messagePattern":"Prepared QQ notification is not valid JSON","errorType":"validation","errorClass":"ConfigurationError","httpStatus":null,"severity":"error","filePath":"script/github/notify_qq.py","lineNumber":251,"sourceCode":"            {\n                \"version\": 1,\n                \"event_name\": event_name,\n                \"repository\": repository,\n                \"message\": message,\n            },\n            ensure_ascii=False,\n        ),\n        encoding=\"utf-8\",\n    )\n\n\ndef _read_prepared_message(path: Path, repository: str) -> tuple[str, str]:\n    if not path.is_file() or path.stat().st_size > 4096:\n        raise ConfigurationError(\"Prepared QQ notification is missing or too large\")\n    try:\n        envelope = json.loads(path.read_text(encoding=\"utf-8\"))\n    except (OSError, UnicodeError, json.JSONDecodeError) as error:\n        raise ConfigurationError(\"Prepared QQ notification is not valid JSON\") from error\n    if not isinstance(envelope, Mapping) or envelope.get(\"version\") != 1:\n        raise ConfigurationError(\"Prepared QQ notification has an invalid format\")\n    if envelope.get(\"repository\") != repository:\n        raise ConfigurationError(\"Prepared QQ notification repository does not match\")\n    event_name = str(envelope.get(\"event_name\") or \"\")\n    if event_name not in COLLECTED_EVENT_NAMES:\n        raise ConfigurationError(\"Prepared QQ notification event is not allowed\")\n    message = envelope.get(\"message\")\n    if not isinstance(message, str) or not message or len(message) > 900:\n        raise ConfigurationError(\"Prepared QQ notification message is invalid\")\n    if re.search(r\"[\\x00-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]\", message):\n        raise ConfigurationError(\"Prepared QQ notification contains control characters\")\n    if re.search(r\"(?i)\\[CQ:\", message):\n        raise ConfigurationError(\"Prepared QQ notification contains a OneBot CQ code\")\n    return event_name, message\n\n\ndef _event_detail(event_name: str, action: str, payload: Mapping[str, Any]) -> str:","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/OtterMind/Chat2DB/blob/5ee1e990e73fbcae1969dc554be254fedb3ab888/script/github/notify_qq.py#L233-L269","documentation":"Thrown by notify_qq._read_prepared_message when reading and JSON-parsing the prepared-message file raises OSError, UnicodeError, or json.JSONDecodeError. The file exists and is within the size cap, but its bytes are not valid UTF-8 JSON.","triggerScenarios":"The drop file was truncated, partially written, encoded in a non-UTF-8 encoding, or overwritten with non-JSON content (e.g. a log line or HTML error page from a failed redirect).","commonSituations":"A concurrent/aborted producer write left a partial file; a redirect or error handler wrote diagnostic text to the same path; encoding mismatch; disk/transfer corruption.","solutions":["Ensure the producer writes atomically (write to a temp file then rename) so the consumer never sees a partial file.","Verify nothing else writes non-JSON content to the drop path.","Confirm the file is UTF-8 encoded; re-run the producer step to regenerate it."],"exampleFix":"# before: producer writes incrementally, consumer reads mid-write\npath.write_text(partial)  # -> not valid JSON\n\n# after: atomic write\ntmp = path.with_suffix('.tmp')\ntmp.write_text(json.dumps(envelope, ensure_ascii=False), encoding='utf-8')\ntmp.replace(path)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    event, msg = _read_prepared_message(path, repo)\nexcept (ConfigurationError, ValueError) as e:\n    print(f\"Invalid prepared message at {path}: {e}\", file=sys.stderr)\n    sys.exit(1)","preventionTips":["Have the producer write atomically (temp file + rename).","Ensure only the sanctioned producer writes the drop path with UTF-8 JSON.","Re-run the producer to regenerate a corrupt file."],"tags":["notify-qq","github-actions","python","json","validation"],"backgroundTag":null,"analyzedSha":"5ee1e990e73fbcae1969dc554be254fedb3ab888","analyzedAt":"2026-08-14T07:05:03.077Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}