{"record":{"id":"4460e3179dd2285d","repo":"grpc/grpc-go","slug":"required-field-subjecttokentype-is-not-specified","errorCode":null,"errorMessage":"required field SubjectTokenType is not specified","messagePattern":"required field SubjectTokenType is not specified","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"credentials/sts/sts.go","lineNumber":227,"sourceCode":"// - 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\n\t}\n\treturn nil\n}","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/credentials/sts/sts.go#L209-L245","documentation":"Returned by sts.validateOptions (credentials/sts/sts.go:227) when opts.SubjectTokenType is empty. SubjectTokenType is the RFC 8693 token-type identifier (e.g. urn:ietf:params:oauth:token-type:jwt) telling the STS server how to interpret the contents of the subject token file; it is Required in the Options struct (line 101). validateOptions enforces ordering — URI checked first, then SubjectTokenPath, then SubjectTokenType.","triggerScenarios":"Calling sts.NewCredentials with SubjectTokenType unset or empty. Because validateOptions checks SubjectTokenPath before SubjectTokenType, you only see this error once SubjectTokenPath is already set.","commonSituations":"Forgetting the token-type URN (it is long and easy to omit); copy-pasting an Options literal that left it blank; using a wrong key name in JSON config so the field stays zero-value.","solutions":["Set Options.SubjectTokenType to the correct RFC 8693 URN for your token (commonly urn:ietf:params:oauth:token-type:jwt or urn:ietf:params:oauth:token-type:access_token).","Confirm the type matches the actual contents of the file at SubjectTokenPath.","Validate the whole Options struct up front and fail startup on any empty required field."],"exampleFix":"// before\nc, _ := sts.NewCredentials(sts.Options{\n    TokenExchangeServiceURI: \"https://sts.googleapis.com/v1/token\",\n    SubjectTokenPath:        \"/var/run/secrets/subject-token\",\n}) // SubjectTokenType 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":"// Ensure a non-empty, well-formed token type URN.\nvar knownTokenTypes = map[string]bool{\n    \"urn:ietf:params:oauth:token-type:jwt\":            true,\n    \"urn:ietf:params:oauth:token-type:access_token\":   true,\n    \"urn:ietf:params:oauth:token-type:id_token\":       true,\n    \"urn:ietf:params:oauth:token-type:saml2\":          true,\n}\nif opts.SubjectTokenType == \"\" || !knownTokenTypes[opts.SubjectTokenType] {\n    return fmt.Errorf(\"SubjectTokenType %q unknown/empty\", opts.SubjectTokenType)\n}","typeGuard":null,"tryCatchPattern":"c, err := sts.NewCredentials(opts)\nif err != nil { log.Fatalf(\"STS creds: %v\", err) }","preventionTips":["Document the allowed token-type URNs in your config template.","Validate the URN against an allow-list so typos fail fast."],"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"}