{"record":{"id":"f3617fd11331d5dc","repo":"mudler/LocalAI","slug":"num-frames-must-not-be-negative","errorCode":null,"errorMessage":"num_frames must not be negative","messagePattern":"num_frames must not be negative","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/python/longcat-video/backend.py","lineNumber":273,"sourceCode":"\n        try:\n            params, ignored_params = select_known_options(\n                dict(request.params), REQUEST_PARAMS\n            )\n            if ignored_params:\n                print(\n                    f\"longcat-video ignoring unknown request param(s): {', '.join(ignored_params)}\",\n                    file=sys.stderr,\n                )\n\n            os.makedirs(os.path.dirname(request.dst) or \".\", mode=0o750, exist_ok=True)\n            if hasattr(context, \"add_callback\"):\n                context.add_callback(interrupt_if_cancelled)\n\n            if request.start_image and not os.path.isfile(request.start_image):\n                raise ValueError(\"start_image is not a readable staged file\")\n            if request.num_frames < 0:\n                raise ValueError(\"num_frames must not be negative\")\n\n            if self.model_kind == MODEL_KIND_BASE:\n                if request.audio:\n                    raise ValueError(\n                        \"audio input requires a LongCat-Video-Avatar-1.5 model\"\n                    )\n                self._generate_base(request, params)\n            else:\n                self._generate_avatar(request, params, context)\n\n            return backend_pb2.Result(\n                message=\"Video generated successfully\", success=True\n            )\n        except ValueError as err:\n            return self._fail(context, grpc.StatusCode.INVALID_ARGUMENT, str(err))\n        except Exception as err:\n            print(f\"Error generating LongCat video: {err}\", file=sys.stderr)\n            traceback.print_exc()","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/mudler/LocalAI/blob/44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26/backend/python/longcat-video/backend.py#L255-L291","documentation":"ValueError from longcat-video's generation RPC: num_frames is a proto int that must be >= 0. Zero means 'derive frame count automatically' (from audio duration or defaults); negative values are meaningless and rejected before dispatch to the base or avatar generation path.","triggerScenarios":"Sending VideoRequest with num_frames=-1 intending 'unlimited' or 'auto' (the correct auto value is 0); computing num_frames from user input that can go negative (e.g. duration*fps - offset).","commonSituations":"Client arithmetic produces a negative count; users coming from APIs where -1 means 'default'.","solutions":["Send num_frames=0 to let the backend choose the frame count automatically","Clamp client-side computed frame counts to >= 0 before building the request"],"exampleFix":"# before\nreq.num_frames = requested_frames  # can be -1\n\n# after\nreq.num_frames = max(0, requested_frames)","handlingStrategy":"validation","validationCode":"def sanitize_video_request(req):\n    if req.num_frames < 0:\n        req.num_frames = 0  # 0 = backend default/derived\n    return req","typeGuard":null,"tryCatchPattern":"try:\n    stub.GenerateVideo(req)\nexcept grpc.RpcError as e:\n    if \"num_frames\" in (e.details() or \"\"):\n        req.num_frames = 0\n        stub.GenerateVideo(req)\n    else:\n        raise","preventionTips":["Clamp all numeric request fields at your API boundary before they reach gRPC","Treat 0 as 'auto' and document that; forbid negative values in client schemas"],"tags":["python","longcat-video","grpc","validation","video-generation"],"backgroundTag":null,"analyzedSha":"44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26","analyzedAt":"2026-08-15T10:13:50.291Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}