{"record":{"id":"cd7a333d495c5735","repo":"temporalio/temporal","slug":"failed-to-deserialize-operationerror-w","errorCode":null,"errorMessage":"failed to deserialize OperationError: %w","messagePattern":"failed to deserialize OperationError: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/nexus/nexusrpc/failure_converter.go","lineNumber":161,"sourceCode":"\t\t\the := &nexus.HandlerError{\n\t\t\t\tMessage:         f.Message,\n\t\t\t\tStackTrace:      f.StackTrace,\n\t\t\t\tType:            nexus.HandlerErrorType(se.Type),\n\t\t\t\tRetryBehavior:   se.RetryBehavior(),\n\t\t\t\tOriginalFailure: &f,\n\t\t\t}\n\t\t\tif f.Cause != nil {\n\t\t\t\the.Cause, err = e.FailureToError(*f.Cause)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn he, nil\n\t\tcase \"nexus.OperationError\":\n\t\t\tvar se serializedOperationError\n\t\t\terr := json.Unmarshal(f.Details, &se)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"failed to deserialize OperationError: %w\", err)\n\t\t\t}\n\t\t\toe := &nexus.OperationError{\n\t\t\t\tMessage:         f.Message,\n\t\t\t\tStackTrace:      f.StackTrace,\n\t\t\t\tState:           nexus.OperationState(se.State),\n\t\t\t\tOriginalFailure: &f,\n\t\t\t}\n\t\t\tif f.Cause != nil {\n\t\t\t\toe.Cause, err = e.FailureToError(*f.Cause)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, err\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn oe, nil\n\t\t}\n\t}\n\t// Note that the original failure cause is retained on the FailureError's failure object.\n\tfe := &nexus.FailureError{Failure: f}","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/nexus/nexusrpc/failure_converter.go#L143-L179","documentation":"Same converter path as the HandlerError case but for failures with metadata type \"nexus.OperationError\": the JSON in f.Details must unmarshal into serializedOperationError (containing the operation State). If it does not, this error is returned because the failure cannot be represented as a nexus.OperationError.","triggerScenarios":"Calling FailureToError on a failure tagged \"nexus.OperationError\" whose Details JSON is invalid or has the wrong fields (e.g. missing/mistyped \"state\"), typically produced by an incompatible writer.","commonSituations":"SDK version skew where the serialized OperationError schema changed; manually built failures in tests; failures round-tripped through systems that re-encode Details as non-JSON (e.g. base64 proto).","solutions":["Inspect f.Metadata and f.Details to confirm the actual wire format of the failure.","Regenerate/produce failures with the matching SDK version so Details uses the expected JSON schema.","Fix any middleware that rewrites Details to preserve the original JSON bytes.","Fall back to handling the raw nexus.Failure when typed conversion fails."],"exampleFix":"// before\noe := err.(*nexus.OperationError) // hard cast after conversion fails\n// after\noe, ok := err.(*nexus.OperationError)\nif !ok {\n    return fmt.Errorf(\"operation failed: %s\", err.Error())\n}","handlingStrategy":"type-guard","validationCode":"if failure.Metadata[\"type\"] == \"nexus.OperationError\" && !json.Valid(failure.Details) {\n    log.Printf(\"malformed OperationError details; treating as generic failure\")\n}","typeGuard":"func isOperationError(err error) (*nexus.OperationError, bool) {\n    oe, ok := err.(*nexus.OperationError)\n    return oe, ok\n}","tryCatchPattern":"err, cerr := converter.FailureToError(failure)\nif cerr != nil {\n    // fall back: inspect State from the raw failure if present, else generic\n    return errors.New(failure.Message)\n}\nvar oe *nexus.OperationError\nif errors.As(err, &oe) && oe.State == nexus.OperationStateFailed {\n    // handle failed operation\n}","preventionTips":["Produce OperationError failures only through nexus.NewOperationError / SDK APIs","Pin matching SDK versions across services sharing Nexus failures","Avoid round-tripping failures through systems that re-encode Details","Always type-assert OperationError instead of hard-casting"],"tags":["nexus","json","deserialization","operation-error"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}