{"record":{"id":"98a8f9e421813c35","repo":"can1357/oh-my-pi","slug":"label-must-be-an-object","errorCode":null,"errorMessage":"${label} must be an object","messagePattern":"(.+?) must be an object","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/launch/protocol.ts","lineNumber":153,"sourceCode":"/** Response envelope kept raw until matched with its pending operation. */\nexport type DaemonWireResponse = { id: string; ok: true; result: unknown } | { id: string; ok: false; error: string };\n\n/** Unsolicited terminal completion sent to the socket that owns a daemon. */\nexport interface DaemonCompletionNotification {\n\tevent: \"daemon-completed\";\n\tcompletionId: string;\n\towner: string;\n\tdaemon: DaemonSnapshot;\n}\n\nexport type DaemonWireMessage = DaemonWireResponse | DaemonCompletionNotification;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction record(value: unknown, label: string): Record<string, unknown> {\n\tif (!isRecord(value)) throw new Error(`${label} must be an object`);\n\treturn value;\n}\n\nfunction stringValue(value: unknown, label: string): string {\n\tif (typeof value !== \"string\" || value.length === 0) throw new Error(`${label} must be a non-empty string`);\n\treturn value;\n}\nfunction rawString(value: unknown, label: string): string {\n\tif (typeof value !== \"string\") throw new Error(`${label} must be a string`);\n\treturn value;\n}\n\nfunction optionalString(value: unknown, label: string): string | undefined {\n\tif (value === undefined) return undefined;\n\treturn stringValue(value, label);\n}\n\nfunction optionalRawString(value: unknown, label: string): string | undefined {","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/launch/protocol.ts#L135-L171","documentation":"The daemon protocol parser validates every decoded payload structurally. record(value, label) is the generic object check used by parseDaemon* functions; any wire payload that is not a plain object (wrong type, null, array) fails with '<label> must be an object', where label names the offending field or message kind.","triggerScenarios":"Sending malformed JSON over the broker socket (e.g. a bare string/number/array where a message object is expected); an RPC result or spec field decoded as the wrong type; null entries in payload arrays.","commonSituations":"Manual JSON-RPC experimentation against the socket; provider/client version skew changing message shapes; serialization bugs writing non-object values into message fields.","solutions":["Log the raw payload and label from the error to identify the malformed field","Ensure the sender serializes messages as JSON objects matching the current DaemonWireMessage schema","Align client and broker versions so both sides agree on message shapes"],"exampleFix":"// before\nsocket.write(JSON.stringify(\"ping\"));\n// after\nsocket.write(JSON.stringify({ op: \"ping\" }));","handlingStrategy":"type-guard","validationCode":"function assertPlainObject(v: unknown, label: string): asserts v is Record<string, unknown> {\n  if (typeof v !== 'object' || v === null || Array.isArray(v)) throw new Error(`${label} must be an object`);\n}","typeGuard":"function isPlainObject(v: unknown): v is Record<string, unknown> {\n  return typeof v === 'object' && v !== null && !Array.isArray(v);\n}","tryCatchPattern":"try {\n  const msg = parseDaemonWireMessage(raw);\n} catch (err) {\n  if (err.message.endsWith('must be an object')) {\n    logger.warn('malformed daemon payload', { raw: String(raw).slice(0, 200) });\n    return;\n  }\n  throw err;\n}","preventionTips":["Run payloads through protocol validators before writing to the socket","Always serialize daemon messages as JSON objects, never scalars or arrays","Version-check peers before exchanging new message shapes"],"tags":["ipc","wire-protocol","schema-validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}