{"record":{"id":"717b6edac51f07bc","repo":"gofiber/fiber","slug":"fiber-failed-to-s-shared-state-s-value-v","errorCode":null,"errorMessage":"fiber: failed to %s shared state %s value: %v","messagePattern":"fiber: failed to (.+?) shared state (.+?) value: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shared_state.go","lineNumber":413,"sourceCode":"\t\treturn sharedStateCodecPanicError(\"decode\", format, recovered)\n\t}\n\tif err != nil {\n\t\treturn fmt.Errorf(\"fiber: failed to decode shared state %s value: %w\", format, err)\n\t}\n\n\treturn nil\n}\n\nfunc sharedStateCodecNotConfiguredError(format, direction string) error {\n\treturn fmt.Errorf(\"fiber: shared state %s %s is not configured\", format, direction)\n}\n\nfunc sharedStateCodecPanicError(operation, format string, recovered any) error {\n\tif err, ok := recovered.(error); ok {\n\t\treturn fmt.Errorf(\"fiber: failed to %s shared state %s value: %w\", operation, format, err)\n\t}\n\n\treturn fmt.Errorf(\"fiber: failed to %s shared state %s value: %v\", operation, format, recovered)\n}\n\nfunc (s *SharedState) storageKey(key string) (string, bool) {\n\tif key == \"\" {\n\t\treturn \"\", false\n\t}\n\n\treturn s.prefix + hex.EncodeToString(utils.UnsafeBytes(key)), true\n}\n","sourceCodeStart":395,"sourceCodeEnd":423,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/shared_state.go#L395-L423","documentation":"Sibling of error 240: sharedStateCodecPanicError fires when the codec panics, but the recovered value does NOT implement error (e.g. panic(\"boom\") with a string, or panic(42)). Fiber formats it with %v because there is no error to wrap. This indicates a custom codec that panics with a non-error value, which is itself a code smell in the codec.","triggerScenarios":"A user-supplied SharedState codec calls panic(\"something\") or panic(someInt) instead of returning an error; the recover() in the encode/decode wrapper catches it and reformats it.","commonSituations":"Hand-written codec that uses panic for control flow; third-party codec that panics on internal assertion failures; porting a codec from another framework without converting panics to errors.","solutions":["Find the codec registered for the failing format and convert every panic into a returned error.","Search the codec source for bare panic(...) calls and replace them with fmt.Errorf returns.","Run the codec under a fuzz test that feeds it malformed input to flush out remaining panic paths."],"exampleFix":"// before: codec panics with a string\nfunc decode(b []byte) (any, error) {\n    if len(b) == 0 { panic(\"empty input\") }\n    ...\n}\n\n// after: return an error\nfunc decode(b []byte) (any, error) {\n    if len(b) == 0 { return nil, fmt.Errorf(\"empty input\") }\n    ...\n}","handlingStrategy":"validation","validationCode":"// Lint your codec for non-error panics before registering it\nfunc auditCodec(c Codec) error {\n    // run against a corpus of inputs under recover; flag any panic\n    for _, in := range badInputs {\n        func() {\n            defer func() { _ = recover() }()\n            _, _ = c.Encode(in)\n        }()\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"// Always recover around third-party codec calls and normalize to error\nfunc callCodec(fn func() error) (err error) {\n    defer func() {\n        if r := recover(); r != nil {\n            if e, ok := r.(error); ok { err = e } else { err = fmt.Errorf(\"codec panic: %v\", r) }\n        }\n    }()\n    return fn()\n}","preventionTips":["Never use panic for control flow in a codec - return errors.","Run codecs under go test -fuzz to flush panic paths.","Wrap third-party codecs with a recover shim that returns an error."],"tags":["shared-state","codec","panic-recovery","bug"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}