{"record":{"id":"2a666df32e4d54d7","repo":"grpc/grpc-go","slug":"required-field-subjecttokenpath-is-not-specified","errorCode":null,"errorMessage":"required field SubjectTokenPath is not specified","messagePattern":"required field SubjectTokenPath is not specified","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"credentials/sts/sts.go","lineNumber":224,"sourceCode":"\n// validateOptions performs the following validation checks on opts:\n// - tokenExchangeServiceURI is not empty\n// - tokenExchangeServiceURI is a valid URI with a http(s) scheme\n// - subjectTokenPath and subjectTokenType are not empty.\nfunc validateOptions(opts Options) error {\n\tif opts.TokenExchangeServiceURI == \"\" {\n\t\treturn errors.New(\"empty token_exchange_service_uri in options\")\n\t}\n\tu, err := url.Parse(opts.TokenExchangeServiceURI)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif u.Scheme != \"http\" && u.Scheme != \"https\" {\n\t\treturn fmt.Errorf(\"scheme is not supported: %q. Only http(s) is supported\", u.Scheme)\n\t}\n\n\tif opts.SubjectTokenPath == \"\" {\n\t\treturn errors.New(\"required field SubjectTokenPath is not specified\")\n\t}\n\tif opts.SubjectTokenType == \"\" {\n\t\treturn errors.New(\"required field SubjectTokenType is not specified\")\n\t}\n\treturn nil\n}\n\n// cachedMetadata returns the cached metadata provided it is not going to\n// expire anytime soon.\n//\n// Caller must hold c.mu.\nfunc (c *callCreds) cachedMetadata() map[string]string {\n\tnow := time.Now()\n\t// If the cached token has not expired and the lifetime remaining on that\n\t// token is greater than the minimum value we are willing to accept, go\n\t// ahead and use it.\n\tif c.tokenExpiry.After(now) && c.tokenExpiry.Sub(now) > minCachedTokenLifetime {\n\t\treturn c.tokenMetadata","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/credentials/sts/sts.go#L206-L242","documentation":"Returned by sts.validateOptions (credentials/sts/sts.go:224) when opts.SubjectTokenPath is empty. The subject token is the file containing the identity token of the party on whose behalf the exchange is made; it is marked Required in the Options struct comment (line 96). Without it the STS request cannot include subject_token, so NewCredentials refuses to construct.","triggerScenarios":"Calling sts.NewCredentials with SubjectTokenPath unset (or empty). The check runs only inside NewCredentials/validateOptions, so this surfaces immediately at construction time.","commonSituations":"Config loaded from a file/env that omits the subject token file path (common when migrating from in-memory tokens to file-based tokens); path field named differently in config vs struct; expecting a default but none exists.","solutions":["Set Options.SubjectTokenPath to the absolute path of the file containing your subject (identity) token.","Verify the path exists and is readable before calling NewCredentials (see also error 20).","Check the returned error from NewCredentials and surface it in startup logs."],"exampleFix":"// before\nc, _ := sts.NewCredentials(sts.Options{\n    TokenExchangeServiceURI: \"https://sts.googleapis.com/v1/token\",\n    SubjectTokenType:        \"urn:ietf:params:oauth:token-type:jwt\",\n}) // SubjectTokenPath missing\n\n// after\nc, err := sts.NewCredentials(sts.Options{\n    TokenExchangeServiceURI: \"https://sts.googleapis.com/v1/token\",\n    SubjectTokenPath:        \"/var/run/secrets/subject-token\",\n    SubjectTokenType:       \"urn:ietf:params:oauth:token-type:jwt\",\n})","handlingStrategy":"validation","validationCode":"if opts.SubjectTokenPath == \"\" {\n    return errors.New(\"SubjectTokenPath must be set to a readable token file\")\n}\nif fi, err := os.Stat(opts.SubjectTokenPath); err != nil || fi.IsDir() {\n    return fmt.Errorf(\"SubjectTokenPath %q not usable: %w\", opts.SubjectTokenPath, err)\n}","typeGuard":null,"tryCatchPattern":"c, err := sts.NewCredentials(opts)\nif err != nil {\n    log.Fatalf(\"cannot build STS creds: %v\", err)\n}","preventionTips":["Treat SubjectTokenPath as required in your own config schema.","Stat-check the file before passing the option.","Fail the process at startup rather than mid-RPC."],"tags":["go","grpc","security","sts","credentials","config-validation"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}