{"record":{"id":"ba4fb80c60fae772","repo":"router-for-me/CLIProxyAPI","slug":"decode-host-log-request-w","errorCode":null,"errorMessage":"decode host log request: %w","messagePattern":"decode host log request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/pluginhost/host_callbacks.go","lineNumber":325,"sourceCode":"}\n\nfunc modelExecutionError(errMsg *interfaces.ErrorMessage) error {\n\tif errMsg == nil {\n\t\treturn nil\n\t}\n\tif errMsg.Error != nil {\n\t\treturn errMsg.Error\n\t}\n\tif errMsg.StatusCode > 0 {\n\t\treturn fmt.Errorf(\"model execution failed with status %d\", errMsg.StatusCode)\n\t}\n\treturn fmt.Errorf(\"model execution failed\")\n}\n\nfunc (h *Host) callHostLog(ctx context.Context, request []byte) ([]byte, error) {\n\tvar req rpcHostLogRequest\n\tif errUnmarshal := json.Unmarshal(request, &req); errUnmarshal != nil {\n\t\treturn nil, fmt.Errorf(\"decode host log request: %w\", errUnmarshal)\n\t}\n\tctx = h.resolveCallbackContext(req.HostCallbackID, ctx)\n\tmessage := strings.TrimSpace(req.Message)\n\tif message == \"\" {\n\t\tmessage = \"plugin log\"\n\t}\n\tfields := log.Fields{}\n\tfor key, value := range req.Fields {\n\t\tkey = strings.TrimSpace(key)\n\t\tif key != \"\" {\n\t\t\tfields[key] = value\n\t\t}\n\t}\n\tif requestID := logging.GetRequestID(ctx); requestID != \"\" {\n\t\tfields[\"request_id\"] = requestID\n\t}\n\tentry := log.WithFields(fields)\n\tswitch strings.ToLower(strings.TrimSpace(req.Level)) {","sourceCodeStart":307,"sourceCodeEnd":343,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/pluginhost/host_callbacks.go#L307-L343","documentation":"callHostLog failed to json.Unmarshal the RPC payload from the plugin into rpcHostLogRequest. This is a protocol-level failure: the plugin sent a host.log callback message whose JSON does not match the expected request shape (wrong field types, unknown structure, truncated bytes).","triggerScenarios":"A plugin's host.log callback with mismatched JSON: Fields values of unexpected types, Message not a string, or a plugin built against a different rpcHostLogRequest schema. The error wraps the encoding/json failure with its position.","commonSituations":"Plugin and host compiled against different pluginhost RPC versions; a plugin marshaling a struct with incompatible field types; corrupted IPC framing producing invalid JSON.","solutions":["Rebuild/update the plugin against the same pluginhost/pluginapi version as the host so the log request schema matches.","Inspect the wrapped json error (it names the field and offset) to see which key mismatches.","In plugin code, only send simple types (string keys, scalar values) in Fields to stay schema-compatible.","If framing corruption is suspected (random offsets), check the plugin transport logs for truncated messages."],"exampleFix":"// plugin side, before\nfields := map[string]any{\"count\": 42, \"nested\": struct{ A int }{1}} // unsupported shape\nhost.Log(\"msg\", fields)\n\n// after\nfields := map[string]any{\"count\": 42} // scalars only\nhost.Log(\"msg\", fields)","handlingStrategy":"validation","validationCode":"// Plugin side: keep log fields to scalars and validate before send\nfields := map[string]any{}\nfor k, v := range raw {\n    switch v.(type) {\n    case string, float64, bool, nil:\n        fields[k] = v\n    default:\n        fields[k] = fmt.Sprintf(\"%v\", v) // stringify anything else\n    }\n}","typeGuard":"func logFieldsRPCSafe(fields map[string]any) bool {\n    for k, v := range fields {\n        if strings.TrimSpace(k) == \"\" {\n            return false\n        }\n        switch v.(type) {\n        case string, float64, bool, nil:\n        default:\n            return false\n        }\n    }\n    return true\n}","tryCatchPattern":"if err := host.Log(message, fields); err != nil {\n    if strings.Contains(err.Error(), \"decode host log request\") {\n        // schema mismatch: fall back to plain message with no fields\n        _ = host.Log(message, nil)\n    }\n}","preventionTips":["Ship plugin and host from the same build so RPC schemas match.","Only send scalar values in log fields; marshal complex structs yourself to a string.","Add a round-trip unit test for every host callback your plugin uses."],"tags":["plugin","rpc","json","logging","schema-mismatch","pluginhost"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}