{"record":{"id":"c99315d60421c2bb","repo":"hashicorp/nomad","slug":"no-identities-requested","errorCode":null,"errorMessage":"no identities requested","messagePattern":"no identities requested","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nomad/alloc_endpoint.go","lineNumber":470,"sourceCode":"// allocations.\n//\n// This is an internal-only RPC and not exposed via the HTTP API.\nfunc (a *Alloc) SignIdentities(args *structs.AllocIdentitiesRequest, reply *structs.AllocIdentitiesResponse) error {\n\n\taclObj, err := a.srv.AuthenticateClientOnly(a.ctx, args)\n\tif done, err := a.srv.forward(\"Alloc.SignIdentities\", args, args, reply); done {\n\t\treturn err\n\t}\n\ta.srv.MeasureRPCRate(\"alloc\", structs.RateMetricRead, args)\n\tif err != nil {\n\t\treturn structs.ErrPermissionDenied\n\t}\n\tdefer metrics.MeasureSince([]string{\"nomad\", \"alloc\", \"sign_identities\"}, time.Now())\n\n\tif len(args.Identities) == 0 {\n\t\t// Client bug. Fail loudly instead of letting clients waste time with\n\t\t// noops.\n\t\treturn fmt.Errorf(\"no identities requested\")\n\t}\n\n\t// Tracks whether the min index was satisfied by the blocking query\n\tthresholdMet := false\n\n\t// Most if not all identity requests will be for the same alloc, so create a\n\t// set of alloc IDs to avoid unnecessary looping in the blocking query.\n\tallocs := make(map[string]*structs.Allocation, len(args.Identities))\n\tfor _, idReq := range args.Identities {\n\t\tallocs[idReq.AllocID] = nil // to be set while watching\n\t}\n\n\topts := blockingOptions{\n\t\tqueryOpts: &args.QueryOptions,\n\t\tqueryMeta: &reply.QueryMeta,\n\t\trun: func(ws memdb.WatchSet, state *state.StateStore) error {\n\t\t\tvar maxIndex uint64\n","sourceCodeStart":452,"sourceCodeEnd":488,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/nomad/alloc_endpoint.go#L452-L488","documentation":"SignIdentities signs workload identity JWTs for allocations, but a request with an empty Identities slice is a client bug and a wasted no-op, so the server fails loudly with 'no identities requested' rather than returning an empty result after a potentially blocking query.","triggerScenarios":"Calling the Alloc.SignIdentities RPC with args.Identities empty — a Nomad client compiled/misbehaving such that it sends zero identity requests, or custom tooling invoking the RPC directly with an empty list.","commonSituations":"Nomad client version mismatch with servers; a client bug when an alloc has no workload identities configured; scripts calling the internal RPC without populating Identities.","solutions":["Ensure the caller populates args.Identities with the workload identity requests before invoking the RPC","Skip the call when there are no identities to sign (no identities configured on the task group)","Upgrade the Nomad client — this is flagged as a client bug, so check for fixed versions"],"exampleFix":"// before\nclient.SignIdentities(args) // Identities: [] — noop\n// after\nif len(args.Identities) == 0 {\n    return nil // nothing to sign\n}\nclient.SignIdentities(args)","handlingStrategy":"validation","validationCode":"if len(req.Identities) == 0 {\n    return nil // nothing to sign; avoid the RPC\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"no identities requested\") {\n    // client bug: log and skip; do not retry identical request\n    return nil\n}","preventionTips":["Only call SignIdentities when the task group defines workload identities","Keep client and server Nomad versions compatible","Validate request payloads before issuing internal RPCs"],"tags":["nomad","rpc","validation","workload-identity"],"backgroundTag":"empty-request-payload","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"}