{"record":{"id":"8e9f747ba21de8b5","repo":"zylon-ai/private-gpt","slug":"schema-must-be-a-dictionary-representing-json-sche","errorCode":null,"errorMessage":"Schema must be a dictionary representing JSON Schema","messagePattern":"Schema must be a dictionary representing JSON Schema","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"private_gpt/chat/schema_models.py","lineNumber":87,"sourceCode":"        \"\"\"Handle reserved BaseModel attributes - conflicts with Pydantic internals.\"\"\"\n        if field_name.lower() in RESERVED_NAMES:\n            return f\"{field_name}_field\"\n        return field_name\n\n    # Apply all sanitization steps in order\n    sanitized = _handle_empty_field_name(field_name)\n    sanitized = _handle_leading_underscores(sanitized)\n    sanitized = _handle_dunder_names(sanitized)\n    sanitized = _handle_python_keywords(sanitized)\n    sanitized = _handle_reserved_basemodel_attributes(sanitized)\n\n    return sanitized\n\n\ndef _validate_json_schema_item(schema: dict[str, Any], strict: bool = True) -> None:\n    \"\"\"Validate that the schema is a valid JSON Schema object.\"\"\"\n    if not isinstance(schema, dict):\n        raise ValueError(\"Schema must be a dictionary representing JSON Schema\")\n\n    if schema == {}:\n        return\n\n    # Handle combinators first\n    if \"oneOf\" in schema:\n        if not isinstance(schema[\"oneOf\"], list):\n            raise ValueError(\"'oneOf' must be an array of schemas\")\n        for sub_schema in schema[\"oneOf\"]:\n            _validate_json_schema_item(sub_schema, strict=False)\n        return  # oneOf schemas don't need type field\n\n    if \"anyOf\" in schema:\n        if not isinstance(schema[\"anyOf\"], list):\n            raise ValueError(\"'anyOf' must be an array of schemas\")\n        for sub_schema in schema[\"anyOf\"]:\n            _validate_json_schema_item(sub_schema, strict=False)\n        return  # anyOf schemas don't need type field","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/chat/schema_models.py#L69-L105","documentation":"Raised by DELETE /skills/{skill_id}/versions/{version} when the parent skill does not exist in the collection. The route checks the skill first; a miss returns 404 before attempting to delete the version.","triggerScenarios":"Deleting a version of a skill that was deleted (whole-skill deletion removes versions); wrong collection parameter; duplicate delete.","commonSituations":"Deleting the entire skill in one session while another session deletes an individual version; stale version list after skill removal.","solutions":["Treat as success if the skill itself is gone — the version is gone with it.","Refresh the version list after any skill-level delete and drop stale rows.","Confirm collection matches before issuing the delete."],"exampleFix":"// before\nawait skillsApi.deleteVersion(id, token, col);\n\n// after\ntry { await skillsApi.deleteVersion(id, token, col); }\ncatch (e) {\n  const skill = await skillsApi.get(id, col).catch(() => null);\n  if (e.status !== 404 || skill) throw e; // 404 + no skill = nothing to do\n}","handlingStrategy":"try-catch","validationCode":"const skill = await skillsApi.get(id, collection).catch(() => null);\nif (!skill) return { deleted: true, viaSkillDeletion: true }; // nothing left","typeGuard":null,"tryCatchPattern":"try { await skillsApi.deleteVersion(id, token, collection); }\ncatch (e) {\n  const skill = await skillsApi.get(id, collection).catch(() => null);\n  if (e.status === 404 && !skill) return; // skill gone -> version gone\n  throw e;\n}","preventionTips":["Drop version rows from UI state when the parent skill is deleted","Make version delete idempotent like skill delete","Serialize skill-level and version-level deletes"],"tags":["fastapi","http-404","skills","versioning","deletion"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}