{"record":{"id":"2b7c2c8eb60da454","repo":"mudler/LocalAI","slug":"audio-input-is-not-a-readable-staged-file","errorCode":null,"errorMessage":"audio input is not a readable staged file","messagePattern":"audio input is not a readable staged file","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/python/longcat-video/backend.py","lineNumber":613,"sourceCode":"            output = self.pipeline.generate_t2v(\n                prompt=request.prompt,\n                negative_prompt=negative_prompt,\n                height=height,\n                width=width,\n                num_frames=frames,\n                num_inference_steps=steps,\n                use_distill=use_distill,\n                guidance_scale=guidance_scale,\n                generator=generator,\n            )[0]\n\n        self._save_video(output, request.dst, fps)\n\n    def _generate_avatar(self, request, params, context):\n        if not request.audio:\n            raise ValueError(\"audio is required for LongCat-Video-Avatar-1.5\")\n        if not os.path.isfile(request.audio):\n            raise ValueError(\"audio input is not a readable staged file\")\n\n        use_distill = self.options[\"use_distill\"]\n        steps = (\n            8\n            if use_distill\n            else require_int(\n                request.step or 50,\n                \"step\",\n                minimum=1,\n                maximum=200,\n            )\n        )\n        text_guidance = (\n            1.0\n            if use_distill\n            else require_float(\n                request.cfg_scale or 4.0,\n                \"cfg_scale\",","sourceCodeStart":595,"sourceCodeEnd":631,"githubUrl":"https://github.com/mudler/LocalAI/blob/44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26/backend/python/longcat-video/backend.py#L595-L631","documentation":"ValueError from _generate_avatar(): request.audio is set but os.path.isfile() fails, so the audio file is not present at that path on the backend host. Like start_image, audio is a staged-file reference, not inline data; the backend later loads it with librosa at 16 kHz mono.","triggerScenarios":"Passing a client-local path never copied to the backend; stale path after the staged file was cleaned up; container path mismatch (file mounted at a different location inside the backend container).","commonSituations":"Distributed setup where the API gateway and the GPU backend do not share a filesystem; temp-file race where the audio is deleted before the request is processed.","solutions":["Copy/upload the audio to a backend-visible location (shared volume) and pass that absolute path","Confirm the file still exists at request time and the backend process has read permission","Prefer wav/mp3 files librosa/ffmpeg can decode"],"exampleFix":"# before\nreq.audio = \"/tmp/client/voice.wav\"\n\n# after\nreq.audio = \"/data/staged/voice.wav\"  # mounted into the backend container","handlingStrategy":"validation","validationCode":"import os\n\ndef validate_staged_audio(audio_path: str) -> str:\n    if not audio_path or not os.path.isfile(audio_path):\n        raise FileNotFoundError(f\"audio not staged on backend: {audio_path!r}\")\n    if os.path.getsize(audio_path) == 0:\n        raise ValueError(f\"audio file is empty: {audio_path}\")\n    return audio_path","typeGuard":null,"tryCatchPattern":"try:\n    stub.GenerateVideo(req)\nexcept grpc.RpcError as e:\n    if \"not a readable staged file\" in (e.details() or \"\"):\n        req.audio = stage_file(req.audio, STAGING_DIR)  # re-stage and retry once\n        stub.GenerateVideo(req)\n    else:\n        raise","preventionTips":["Use a shared staging volume and verify readability from the backend side before each request","Include file existence checks in request-building helpers"],"tags":["python","longcat-video","grpc","file-handling","audio"],"backgroundTag":null,"analyzedSha":"44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26","analyzedAt":"2026-08-15T10:13:50.291Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}