{"record":{"id":"ca6fc16e946b3cd8","repo":"ory/hydra","slug":"errkeycannotbetypeasserted","errorCode":"ErrKeyCanNotBeTypeAsserted","errorMessage":"key could not be type asserted","messagePattern":"key could not be type asserted","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"oryx/mapx/type_assert.go","lineNumber":17,"sourceCode":"// Copyright © 2023 Ory Corp\n// SPDX-License-Identifier: Apache-2.0\n\npackage mapx\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"math\"\n\t\"time\"\n)\n\n// ErrKeyDoesNotExist is returned when the key does not exist in the map.\nvar ErrKeyDoesNotExist = errors.New(\"key is not present in map\")\n\n// ErrKeyCanNotBeTypeAsserted is returned when the key can not be type asserted.\nvar ErrKeyCanNotBeTypeAsserted = errors.New(\"key could not be type asserted\")\n\n// GetString returns a string for a given key in values.\nfunc GetString[K comparable](values map[K]any, key K) (string, error) {\n\tif v, ok := values[key]; !ok {\n\t\treturn \"\", ErrKeyDoesNotExist\n\t} else if sv, ok := v.(string); !ok {\n\t\treturn \"\", ErrKeyCanNotBeTypeAsserted\n\t} else {\n\t\treturn sv, nil\n\t}\n}\n\n// GetStringSlice returns a string slice for a given key in values.\nfunc GetStringSlice[K comparable](values map[K]any, key K) ([]string, error) {\n\tv, ok := values[key]\n\tif !ok {\n\t\treturn nil, ErrKeyDoesNotExist\n\t}","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/ory/hydra/blob/4174065ffb052799890f7480f5360a877a67ffc1/oryx/mapx/type_assert.go#L1-L35","documentation":"ErrKeyCanNotBeTypeAsserted is a sentinel error returned by oryx/mapx helpers (GetString, GetStringSlice, GetTime, GetInt64, GetFloat64, and claim parsers) when the key exists in the map but the stored value's concrete type is not the type the helper expects. It indicates a type mismatch in map[string]any / map[K]any data, not a missing key (that is ErrKeyDoesNotExist). The library throws it so callers can distinguish 'wrong shape' data from absent data.","triggerScenarios":"Calling mapx.GetString on a key whose value is not a string (e.g. claims[\"aud\"] holding []string or float64); calling GetTime on a value that is not one of the supported numeric/time types; calling GetInt64 on a non-numeric value; ParseMapInterfaceInterfaceClaims encountering a JWT claim of unexpected type.","commonSituations":"JWT claims where 'aud' is sometimes a single string and sometimes an array depending on the issuer; decoded JSON numbers arriving as float64 when a string was expected; upstream services or token issuers changing claim types; hand-built config maps with the wrong value type.","solutions":["Check the actual Go type of the map value before calling the typed getter (e.g. switch v := claims[\"aud\"].(type)).","Follow the pattern used in oryx/jwtx/claims.go:57: try GetString first and fall back to GetStringSlice on ErrKeyCanNotBeTypeAsserted to handle both single-value and multi-value claims.","Fix the producer of the map so it stores the expected type for the key.","If only presence matters, check for ErrKeyDoesNotExist separately so a type mismatch is not confused with a missing key."],"exampleFix":"// before\naud, err := mapx.GetString(claims, \"aud\")\n// after\naud, err := mapx.GetString(claims, \"aud\")\nif errors.Is(err, mapx.ErrKeyCanNotBeTypeAsserted) {\n    var auds []string\n    auds, err = mapx.GetStringSlice(claims, \"aud\")\n    if err == nil {\n        result.Audience = auds\n    }\n}","handlingStrategy":"type-guard","validationCode":"v, ok := claims[\"aud\"]\nif !ok { /* missing key path */ }\nswitch v.(type) {\ncase string, []string:\n    // safe to call GetString / GetStringSlice\ndefault:\n    // wrong type; handle before calling mapx\n}","typeGuard":"func isStringOrStringSlice(v any) bool {\n    switch v.(type) {\n    case string, []string:\n        return true\n    }\n    return false\n}","tryCatchPattern":"aud, err := mapx.GetString(claims, \"aud\")\nif errors.Is(err, mapx.ErrKeyCanNotBeTypeAsserted) {\n    auds, err2 := mapx.GetStringSlice(claims, \"aud\")\n    if err2 != nil { /* handle: neither string nor []string */ }\n    result.Audience = auds\n} else if err != nil {\n    // other error (e.g. ErrKeyDoesNotExist)\n} else {\n    result.Audience = []string{aud}\n}","preventionTips":["Always compare with errors.Is against the mapx sentinel errors, never == on wrapped errors.","Handle string-vs-[]string claim duality (like 'aud') explicitly at parse time.","Log the actual Go type (%T) of offending values when the error occurs to debug the producer.","Keep a single claim-parsing helper so type fallbacks are consistent across the codebase."],"tags":["go","type-assertion","mapx","jwt-claims"],"backgroundTag":"type-assertion-failed","analyzedSha":"4174065ffb052799890f7480f5360a877a67ffc1","analyzedAt":"2026-09-03T14:52:41.581Z","contentChangedAt":"2026-09-03T14:52:41.581Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}