{"record":{"id":"8dccf9d024e8f866","repo":"can1357/oh-my-pi","slug":"text-must-be-a-string","errorCode":null,"errorMessage":"text must be a string","messagePattern":"text must be a string","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/tui/src/debug-server.ts","lineNumber":363,"sourceCode":"\t\t\t\t\tpid: process.pid,\n\t\t\t\t\toverlays: this.#tui.overlayStack.length,\n\t\t\t\t\tfocused: focused === null ? null : componentKind(focused),\n\t\t\t\t\talt_screen: paint?.altScreen ?? false,\n\t\t\t\t\tcursor: paint?.cursor ?? { visible: false },\n\t\t\t\t};\n\t\t\t}\n\t\t\tcase \"keys\": {\n\t\t\t\tif (typeof request.keys !== \"string\") throw new Error(\"keys must be a string\");\n\t\t\t\tconst parsed = parseKeyTokens(request.keys);\n\t\t\t\tfor (const sequence of parsed.sequences) this.#tui.injectDebugInput(sequence);\n\t\t\t\treturn { ok: true, injected: parsed.events };\n\t\t\t}\n\t\t\tcase \"bytes\":\n\t\t\t\tif (typeof request.data !== \"string\") throw new Error(\"data must be a string\");\n\t\t\t\tthis.#tui.injectDebugInput(request.data);\n\t\t\t\treturn { ok: true };\n\t\t\tcase \"paste\":\n\t\t\t\tif (typeof request.text !== \"string\") throw new Error(\"text must be a string\");\n\t\t\t\tthis.#tui.injectDebugInput(`\\x1b[200~${request.text}\\x1b[201~`);\n\t\t\t\treturn { ok: true };\n\t\t\tcase \"mouse\": {\n\t\t\t\tif (typeof request.x !== \"number\" || typeof request.y !== \"number\")\n\t\t\t\t\tthrow new Error(\"mouse x and y must be numbers\");\n\t\t\t\tconst action = request.action === undefined ? \"click\" : request.action;\n\t\t\t\tif (typeof action !== \"string\") throw new Error(\"mouse action must be a string\");\n\t\t\t\tthis.#tui.injectDebugInput(mouseSequence(request.x, request.y, action));\n\t\t\t\treturn { ok: true };\n\t\t\t}\n\t\t\tcase \"quit\":\n\t\t\t\treturn { ok: true };\n\t\t\tdefault:\n\t\t\t\treturn { ok: false, error: `unknown op ${request.op}` };\n\t\t}\n\t}\n\n\t#node(component: Component): TuiDebugTreeNode {","sourceCodeStart":345,"sourceCodeEnd":381,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/tui/src/debug-server.ts#L345-L381","documentation":"For the debug server's \"paste\" operation, #dispatch requires request.text to be a string; it is wrapped in bracketed-paste markers (ESC[200~ ... ESC[201~) and injected into the TUI. If text is missing or not a string, this error is thrown and returned as a failed response.","triggerScenarios":"Sending {\"op\":\"paste\"} without text; sending text as a number, array, or object; mixing up field names with the \"bytes\" op (data) or \"keys\" op (keys).","commonSituations":"Clipboard clients that pass a buffer or lines array instead of joining to a single string; template reuse across ops sending the wrong field name.","solutions":["Set text to the string you want pasted, e.g. {\"op\":\"paste\",\"text\":\"hello\"}","Join multiline clipboards into one string with \\n separators","For the paste op use the field name text, not data or keys"],"exampleFix":"// before\n{ \"op\": \"paste\", \"text\": [\"line1\", \"line2\"] }\n// after\n{ \"op\": \"paste\", \"text\": \"line1\\nline2\" }","handlingStrategy":"validation","validationCode":"if (typeof request.text !== \"string\")\n  request.text = Array.isArray(request.text) ? request.text.join(\"\\n\") : String(request.text);","typeGuard":"function hasStringText(r: { op: string; text?: unknown }): r is { op: \"paste\"; text: string } {\n  return r.op === \"paste\" && typeof r.text === \"string\";\n}","tryCatchPattern":"try {\n  const res = await send({ op: \"paste\", text });\n} catch (err) {\n  if (String(err.message) === \"text must be a string\") {\n    text = String(text);\n  }\n}","preventionTips":["Coerce clipboard content to a string before sending","Use the correct field name per op: text for paste, data for bytes, keys for keys","Validate request payloads against a shared schema before writing to the socket"],"tags":["validation","types","debug-server"],"backgroundTag":"invalid-request-field-type","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}