{"record":{"id":"2326a11c1f0038b0","repo":"can1357/oh-my-pi","slug":"type-must-be-a-string-or-non-empty-array-of-string","errorCode":null,"errorMessage":"type must be a string or non-empty array of strings","messagePattern":"type must be a string or non-empty array of strings","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/yield.ts","lineNumber":103,"sourceCode":"\t\t\titems: { type: \"string\" },\n\t\t},\n\t],\n\tdescription: \"Optional result type. A non-empty string array is incremental; a string is terminal.\",\n};\n\nfunction isYieldType(value: unknown): value is string | string[] {\n\treturn (\n\t\ttypeof value === \"string\" ||\n\t\t(Array.isArray(value) && value.length > 0 && value.every(item => typeof item === \"string\"))\n\t);\n}\n\nfunction parseYieldType(value: unknown): string | string[] | undefined {\n\t// Strict-mode providers (OpenAI/Codex) make the optional `type` property\n\t// required+nullable, so an untyped final yield arrives as `type: null`.\n\tif (value === undefined || value === null) return undefined;\n\tif (isYieldType(value)) return value;\n\tthrow new Error(\"type must be a string or non-empty array of strings\");\n}\n/** Parse a `{`/`[`-leading JSON string; undefined on non-container or parse failure. */\nfunction parseJsonContainerString(value: string): unknown {\n\tconst trimmed = value.trim();\n\tif (!(trimmed.startsWith(\"{\") || trimmed.startsWith(\"[\"))) return undefined;\n\ttry {\n\t\treturn JSON.parse(trimmed);\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * Resolve the `result` record from raw yield arguments, losslessly salvaging","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/yield.ts#L85-L121","documentation":"The yield tool's optional `type` parameter classifies the result (string or non-empty array of strings). parseYieldType accepts undefined/null (treated as untyped) and valid shapes, and throws a plain Error for anything else — e.g. numbers, empty arrays, or arrays containing non-strings. Note strict-mode providers can deliver `type: null`, which is deliberately tolerated.","triggerScenarios":"Passing `type: 42`, `type: true`, `type: {}`, `type: []` (empty array), or `type: [1,2]` in the yield tool parameters.","commonSituations":"A model emits a numeric type code or an empty array when it has no classification; prompt/schema drift causes the model to fill `type` with an invalid literal.","solutions":["Omit `type` entirely (or send null) when there is no classification.","Send a single string, e.g. \"finding\".","Send a non-empty array of strings for multiple classifications, e.g. [\"security\",\"high\"].","Ensure all array elements are strings — convert enums/numbers to strings before passing."],"exampleFix":"// before\nyield({ result: { data: x }, type: [] })\n// after\nyield({ result: { data: x }, type: \"finding\" })","handlingStrategy":"type-guard","validationCode":"const t = (p: { type?: unknown }).type; if (t !== undefined && t !== null && typeof t !== \"string\" && !(Array.isArray(t) && t.length > 0 && t.every((s) => typeof s === \"string\"))) throw new Error(\"type must be a string or non-empty array of strings\");","typeGuard":"function isYieldType(v: unknown): v is string | string[] { return typeof v === \"string\" || (Array.isArray(v) && v.length > 0 && v.every((s) => typeof s === \"string\")); }","tryCatchPattern":"try { yield(params); } catch (e) { if (e.message === \"type must be a string or non-empty array of strings\") { delete params.type; return yield(params); } throw e; }","preventionTips":["Only pass strings or non-empty string arrays as `type`.","Omit `type` when there is no classification (null is tolerated).","Stringify enum values before assigning to `type`.","Add a schema/constraint on `type` in generated prompts."],"tags":["validation","yield","parameters"],"backgroundTag":"invalid-parameter-type","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}