{"record":{"id":"6ed8d467cf6a1dae","repo":"temporalio/temporal","slug":"failed-to-deserialize-handlererror-w","errorCode":null,"errorMessage":"failed to deserialize HandlerError: %w","messagePattern":"failed to deserialize HandlerError: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/nexus/nexusrpc/failure_converter.go","lineNumber":141,"sourceCode":"\t\t}\n\t\treturn f, nil\n\tdefault:\n\t\treturn nexus.Failure{\n\t\t\tMessage: typedErr.Error(),\n\t\t}, nil\n\t}\n}\n\n// FailureToError implements FailureConverter.\n// nolint:revive // Keeping all of the logic together for readability, even if it means the function is long.\nfunc (e knownErrorFailureConverter) FailureToError(f nexus.Failure) (error, error) {\n\tif f.Metadata != nil {\n\t\tswitch f.Metadata[\"type\"] {\n\t\tcase \"nexus.HandlerError\":\n\t\t\tvar se serializedHandlerError\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 HandlerError: %w\", err)\n\t\t\t}\n\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)","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/nexus/nexusrpc/failure_converter.go#L123-L159","documentation":"FailureToError converts a Nexus failure with metadata type \"nexus.HandlerError\" back into a nexus.HandlerError. The typed details are stored as JSON in f.Details; if that JSON cannot be unmarshaled into serializedHandlerError, the failure metadata is corrupt or from an incompatible producer, so this error is returned.","triggerScenarios":"Receiving a Nexus failure whose Details field is not valid JSON matching the serializedHandlerError shape — e.g. a failure created by hand, by a different SDK version, or truncated in transit — then calling FailureToError.","commonSituations":"Version skew between services producing/consuming failures; a proxy or middleware rewriting the failure payload; manually constructed failures in tests; corrupted persistence of failure details.","solutions":["Log the raw failure (Metadata and Details) to see the malformed content and identify the producer.","Ensure all services produce failures via the SDK's ErrorToFailure so Details is valid serializedHandlerError JSON.","Align SDK versions across producer and consumer services.","As a fallback, treat the original *nexus.Failure as a generic failure instead of failing the conversion."],"exampleFix":"// before\nhe, err := converter.FailureToError(failure) // panics on malformed details\n// after\nhe, err := converter.FailureToError(failure)\nif err != nil {\n    logger.Warn(\"unrecognized nexus failure details\", \"error\", err)\n    return errors.New(failure.Message)\n}","handlingStrategy":"fallback","validationCode":"if failure.Metadata[\"type\"] == \"nexus.HandlerError\" && !json.Valid(failure.Details) {\n    log.Printf(\"malformed HandlerError details from producer; using generic failure\")\n}","typeGuard":"func isHandlerErrorFailure(f *nexus.Failure) bool {\n    return f != nil && f.Metadata[\"type\"] == \"nexus.HandlerError\" && json.Valid(f.Details)\n}","tryCatchPattern":"err, cerr := converter.FailureToError(failure)\nif cerr != nil {\n    // fall back to the raw failure rather than losing information\n    return errors.New(failure.Message + \": \" + cerr.Error())\n}\nreturn err","preventionTips":["Always construct failures via the SDK's ErrorToFailure, never by hand","Keep SDK versions aligned across all producing/consuming services","Do not let middleware rewrite failure Details bytes","Log raw failure metadata when conversion fails to aid debugging"],"tags":["nexus","json","deserialization","failure-conversion"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}