{"record":{"id":"20a7b87ae50d0c82","repo":"hashicorp/nomad","slug":"missing-allocid-20a7b8","errorCode":null,"errorMessage":"missing AllocID","messagePattern":"missing AllocID","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"nomad/client_fs_endpoint.go","lineNumber":254,"sourceCode":"\t}\n\n\tauthErr := f.srv.Authenticate(nil, &args)\n\n\t// Check if we need to forward to a different region\n\tif r := args.RequestRegion(); r != f.srv.Region() {\n\t\tforwardRegionStreamingRpc(f.srv, conn, encoder, &args, \"FileSystem.Stream\",\n\t\t\targs.AllocID, &args.QueryOptions)\n\t\treturn\n\t}\n\tf.srv.MeasureRPCRate(\"file_system\", structs.RateMetricRead, &args)\n\tif authErr != nil {\n\t\thandleStreamResultError(structs.ErrPermissionDenied, nil, encoder)\n\t\treturn\n\t}\n\n\t// Verify the arguments.\n\tif args.AllocID == \"\" {\n\t\thandleStreamResultError(errors.New(\"missing AllocID\"), new(int64(400)), encoder)\n\t\treturn\n\t}\n\n\t// Retrieve the allocation\n\tsnap, err := f.srv.State().Snapshot()\n\tif err != nil {\n\t\thandleStreamResultError(err, nil, encoder)\n\t\treturn\n\t}\n\n\talloc, err := getAlloc(snap, args.AllocID)\n\tif structs.IsErrUnknownAllocation(err) {\n\t\thandleStreamResultError(structs.NewErrUnknownAllocation(args.AllocID), new(int64(404)), encoder)\n\t\treturn\n\t}\n\tif err != nil {\n\t\thandleStreamResultError(err, nil, encoder)\n\t\treturn","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/client_fs_endpoint.go#L236-L272","documentation":"Inside the filesystem streaming endpoint (used by Stream/Log/Read paths), args.AllocID is validated after ACL checks. As this is a streaming RPC, the \"missing AllocID\" error is delivered over the stream via handleStreamResultError with code 400 and the stream is closed. The request had no allocation to stream file contents from.","triggerScenarios":"Opening a StreamingFsOperation (or StreamFrames-based FS call) with the request's AllocID left as \"\".","commonSituations":"Custom log streaming clients (like nomad log tailers) failing to set AllocID; CLI flag defaults leaving the ID empty; reconnection logic that drops the alloc ID between reconnect attempts.","solutions":["Set AllocID on the FS streaming request before opening the stream.","Resolve and cache the alloc ID before each (re)connection attempt.","Handle the streamed 400 error frame in your streaming client.","Validate AllocID non-empty before dialing the stream."],"exampleFix":"// before\nreq := structs.FsStreamRequest{Path: \"logs/app.log\", Follow: true}\nfs.Stream(ctx, req, ...)\n// after\nreq := structs.FsStreamRequest{AllocID: alloc.ID, Path: \"logs/app.log\", Follow: true}\nfs.Stream(ctx, req, ...)","handlingStrategy":"validation","validationCode":"if allocID == \"\" {\n    return fmt.Errorf(\"FS stream requires a non-empty AllocID\")\n}\n// proceed to open streaming FS RPC","typeGuard":"func streamRequestValid(req *structs.FsStreamRequest) bool {\n    return req != nil && req.AllocID != \"\" && req.Origin != \"\"\n}","tryCatchPattern":"// streaming RPC: consume error frames\nfor {\n    frame, err := recv(stream)\n    if err != nil { return err }\n    if frame.IsError {\n        return fmt.Errorf(\"fs stream failed (code %d): %s\", frame.Error.Code, frame.Error.Message)\n    }\n    // process data frames\n}","preventionTips":["Set AllocID before opening any FS streaming call (Stream/Read/Logs).","Re-validate the alloc ID on every stream reconnect — reconnection code often drops it.","Treat 400 error frames from the stream as fatal configuration issues, not retryable ones."],"tags":["nomad","rpc","streaming","filesystem","argument-validation"],"backgroundTag":"missing-required-argument","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}