{"record":{"id":"34e8c889800ad7a3","repo":"zylon-ai/private-gpt","slug":"audio-size-audio-size-exceeds-maximum-allowed-si","errorCode":null,"errorMessage":"Audio size {audio_size} exceeds maximum allowed size of {settings().chat.maximum_blob_size} bytes.","messagePattern":"Audio size (.+?) exceeds maximum allowed size of (.+?) bytes\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"private_gpt/chat/input_models.py","lineNumber":920,"sourceCode":"                image_size = len(image_bytes.read())\n                if image_size > settings().chat.maximum_blob_size:\n                    raise ValueError(\n                        f\"Image size {image_size} exceeds maximum \"\n                        f\"allowed size of {settings().chat.maximum_blob_size} bytes.\"\n                    )\n\n                image_bytes.seek(0)\n                blocks.append(\n                    LIImageBlock(\n                        image=image_bytes.read(),\n                        image_mimetype=block.source.get_media_type(),\n                    )\n                )\n            elif isinstance(block, AudioBlock):\n                audio_bytes = load_file_from_uri(block.source.get_data())\n                audio_size = len(audio_bytes.read())\n                if audio_size > settings().chat.maximum_blob_size:\n                    raise ValueError(\n                        f\"Audio size {audio_size} exceeds maximum \"\n                        f\"allowed size of {settings().chat.maximum_blob_size} bytes.\"\n                    )\n                audio_bytes.seek(0)\n                blocks.append(\n                    LIAudioBlock(\n                        audio=audio_bytes.read(),\n                        format=block.source.get_media_type(),\n                    )\n                )\n            elif isinstance(block, ContentBlockType):\n                if block.type not in custom_blocks:\n                    custom_blocks[block.type] = []\n                custom_blocks[block.type].append(block)\n\n        return blocks if blocks else None, custom_blocks if custom_blocks else None\n\n    def _convert_message(self) -> list[ChatMessage]:","sourceCodeStart":902,"sourceCodeEnd":938,"githubUrl":"https://github.com/zylon-ai/private-gpt/blob/4a030776a31a901ad80b1bf4d7faa2c1a367efbb/private_gpt/chat/input_models.py#L902-L938","documentation":"Raised by POST /skills/{skill_id}/versions when SkillService.create_version() returns None — meaning the skill disappeared between the initial existence check and the actual version write (or the service otherwise could not resolve it). It is a second, service-level not-found guard after form parsing and file storage have already run.","triggerScenarios":"The skill is deleted concurrently while the multipart upload/version creation is in progress; service-layer lookup failing under the same race.","commonSituations":"Two actors operating on the same skill (one deleting, one versioning); long uploads widening the race window.","solutions":["Retry once: re-check existence, then re-submit the version if the skill is still present.","Serialize skill mutations per skill id in the client to avoid delete/version races.","If consistently reproducible, verify the service's storage for the skill id is intact."],"exampleFix":"// before\nawait skillsApi.createVersion(id, col, files); // may 404 mid-flight\n\n// after\ntry { await skillsApi.createVersion(id, col, files); }\ncatch (e) {\n  if (e.status === 404 && (await skillsApi.get(id, col).catch(() => null))) {\n    return skillsApi.createVersion(id, col, files); // retry once\n  }\n  throw e;\n}","handlingStrategy":"retry","validationCode":"const stillThere = await skillsApi.get(id, collection).catch(() => null);\nif (!stillThere) throw new SkillGoneError(id);","typeGuard":null,"tryCatchPattern":"try { return await skillsApi.createVersion(id, collection, files); }\ncatch (e) {\n  if (e.status === 404 && (await skillsApi.get(id, collection).catch(() => null))) {\n    return skillsApi.createVersion(id, collection, files); // transient race: retry once\n  }\n  throw e;\n}","preventionTips":["Serialize mutations per skill id (lock/delete/version) in the client","Keep upload windows short to narrow the race","Retry once on 404 only when the skill verifiably still exists"],"tags":["fastapi","http-404","skills","versioning","race-condition"],"backgroundTag":null,"analyzedSha":"4a030776a31a901ad80b1bf4d7faa2c1a367efbb","analyzedAt":"2026-08-15T03:51:26.951Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}