{"record":{"id":"7e557aab73b3673f","repo":"dgraph-io/dgraph","slug":"couldn-t-parse-max-age","errorCode":null,"errorMessage":"Couldn't Parse max-age","messagePattern":"Couldn't Parse max-age","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"graphql/authorization/utils.go","lineNumber":25,"sourceCode":"\nimport (\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/pkg/errors\"\n)\n\nfunc ParseMaxAge(CacheControlHeaderStr string) (int64, error) {\n\tsplittedHeaderStr := strings.Split(CacheControlHeaderStr, \",\")\n\tfor _, str := range splittedHeaderStr {\n\t\tstrTrimSpace := strings.TrimSpace(str)\n\t\tif strings.HasPrefix(strTrimSpace, \"max-age\") || strings.HasPrefix(strTrimSpace, \"s-maxage\") {\n\t\t\tmaxAge, err := strconv.Atoi(strings.Split(str, \"=\")[1])\n\t\t\treturn int64(maxAge), err\n\t\t}\n\t}\n\treturn 0, errors.Errorf(\"Couldn't Parse max-age\")\n}\n\nfunc ParseExpires(ExpiresHeaderStr string) (int64, error) {\n\texpDate, err := time.Parse(time.RFC1123, ExpiresHeaderStr)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tcurrDate := time.Now().Round(time.Second)\n\tdiff := expDate.Sub(currDate).Seconds()\n\treturn int64(diff), nil\n}\n","sourceCodeStart":7,"sourceCodeEnd":37,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/graphql/authorization/utils.go#L7-L37","documentation":"ParseMaxAge extracts the max-age value from a Cache-Control header string. If the string contains neither a 'max-age' nor 's-maxage' directive, it returns this error. FetchJWK uses it to cache JSON Web Keys, so it signals the HTTP response had no parseable cache lifetime.","triggerScenarios":"Calling FetchJWK against a JWKS endpoint whose response has a Cache-Control header without max-age/s-maxage, or a header that fails strconv.Atoi on the value after '='.","commonSituations":"JWKS server sends 'Cache-Control: no-cache' or 'no-store'; malformed header like 'max-age=abc'; header with quotes around the value ('max-age=\"3600\"').","solutions":["Ensure the JWKS endpoint returns a Cache-Control header with a valid max-age or s-maxage integer","Add an Expires header as fallback (ParseExpires handles it)","Return valid cache headers from the identity provider / reverse proxy","Handle the error in FetchJWK by falling back to a default cache duration"],"exampleFix":"// before\nCache-Control: no-store\n// after\nCache-Control: public, max-age=3600","handlingStrategy":"fallback","validationCode":"const m = cacheControl.match(/(?:s-)?max-age=(\\d+)/);\nif (!m) console.warn('no max-age in Cache-Control header:', cacheControl);","typeGuard":null,"tryCatchPattern":"try {\n  ttl = ParseMaxAge(cacheControl);\n} catch (err) {\n  ttl = defaultJWKCacheTTL; // e.g. 60s\n}","preventionTips":["Configure JWKS endpoints to emit Cache-Control with max-age","Also supply an Expires header as a secondary source","Wrap ParseMaxAge with a safe default duration","Log the raw header when parsing fails for easier diagnosis"],"tags":["http-headers","jwk","parsing"],"backgroundTag":"cache-control-parse-failed","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}