{"record":{"id":"664017fb41df7f04","repo":"abhigyanpatwari/GitNexus","slug":"opencode-cli-returned-no-text-output","errorCode":null,"errorMessage":"OpenCode CLI returned no text output","messagePattern":"OpenCode CLI returned no text output","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"gitnexus/src/core/wiki/local-cli-client.ts","lineNumber":217,"sourceCode":"\n    if (event.type === 'error') {\n      const message =\n        event.error?.data?.message ||\n        event.error?.name ||\n        event.message ||\n        event.part?.text ||\n        line;\n      throw new Error(`OpenCode CLI returned error event: ${message}`);\n    }\n\n    if (event.type === 'text' && typeof event.part?.text === 'string') {\n      textParts.push(event.part.text);\n    }\n  }\n\n  const content = textParts.join('').trim();\n  if (!content) {\n    throw new Error('OpenCode CLI returned no text output');\n  }\n  return content;\n}\n\nfunction buildChildEnv(provider: LocalAgentProvider): NodeJS.ProcessEnv {\n  const env: NodeJS.ProcessEnv = {\n    ...process.env,\n    CI: '1',\n  };\n\n  if (provider === 'opencode') {\n    delete env.OPENCODE_SERVER_PASSWORD;\n    delete env.OPENCODE_SERVER_USERNAME;\n  }\n\n  return env;\n}\n","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/52924ef12c2290ceee4612526a828ec4cdf2047f/gitnexus/src/core/wiki/local-cli-client.ts#L199-L235","documentation":"callOpenCodeLLM spawns `opencode run --format json` and accumulates stdout events, keeping only parts where event.type === 'text' with a string event.part.text. If the joined, trimmed content is empty, the CLI ran to completion but produced zero usable text parts, so this error is thrown. It means the OpenCode process itself succeeded at the transport level while delivering no model text.","triggerScenarios":"Calling callOpenCodeLLM (GitNexus wiki generation with local provider 'opencode') when the model emits only non-text events (step start/end, tool-call parts), when OpenCode is not authenticated or its model provider is misconfigured so it returns nothing, when stdout is polluted with non-JSON warnings the parser skips, or when an older/newer opencode version emits a different JSON event schema than the parser expects.","commonSituations":"Fresh machine where `opencode` is installed but `opencode auth login` was never run; OPENCODE_MODEL or ~/.config/opencode pointing at a provider/key that is broken; opencode version skew after upgrading GitNexus (event part shapes changed across opencode releases); models that answer with only reasoning or tool events and no final text part.","solutions":["Smoke-test the CLI exactly as GitNexus invokes it: run `opencode run --format json \"Reply with the word ok\"` in the same working directory and confirm a text part appears.","Authenticate and configure the model: `opencode auth login`, then check the model/provider config (`opencode models`) or set the model explicitly via GitNexus config.model.","Align versions: update opencode (and GitNexus) so the `--format json` event schema matches what local-cli-client.ts parses.","If the model reliably returns no text parts, switch the wiki generator to a different LocalAgentProvider or disable local-LLM wiki generation.","Report the captured stdout JSON events in a GitNexus issue if a text-bearing event shape is present but unrecognized."],"exampleFix":"// before: model not pinned / not authenticated\ngitnexus wiki generate --provider opencode\n// → Error: OpenCode CLI returned no text output\n\n// after: verify auth, pin a known-good model, then retry\nopencode auth login\nopencode run --format json \"say ok\"   # confirm a text part is emitted\n# gitnexus config (wiki generation)\n{ \"provider\": \"opencode\", \"model\": \"anthropic/claude-sonnet-4-5\" }\ngitnexus wiki generate --provider opencode","handlingStrategy":"fallback","validationCode":"// Preflight: confirm the CLI produces text parts before relying on it\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nconst run = promisify(execFile);\n\nasync function opencodeProducesText(dir: string): Promise<boolean> {\n  try {\n    const { stdout } = await run('opencode', ['run', '--format', 'json', '--dir', dir, 'Reply with: ok'], { timeout: 60_000 });\n    return stdout.split('\\n').some((l) => {\n      try { const e = JSON.parse(l); return e.type === 'text' && typeof e.part?.text === 'string' && e.part.text.trim(); }\n      catch { return false; }\n    });\n  } catch { return false; }\n}","typeGuard":"const isTextPartEvent = (\n  e: unknown,\n): e is { type: 'text'; part: { text: string } } =>\n  typeof e === 'object' && e !== null &&\n  (e as { type?: unknown }).type === 'text' &&\n  typeof (e as { part?: { text?: unknown } }).part?.text === 'string';","tryCatchPattern":"try {\n  const res = await callOpenCodeLLM(prompt, config, systemPrompt);\n} catch (err) {\n  if (err instanceof Error && err.message === 'OpenCode CLI returned no text output') {\n    // empty-but-successful run: log events, switch provider or model, do not blind-retry the same setup\n    logger.warn('opencode returned no text; falling back', { model: config.model });\n    return callCodexLLM(prompt, config, systemPrompt); // or mark wiki section as skipped\n  }\n  throw err;\n}","preventionTips":["Pin config.model to a model you have verified emits text parts with `opencode run --format json`.","Run `opencode auth login` and smoke-test the CLI in the same --dir before enabling wiki generation.","Keep opencode and gitnexus versions aligned; the JSON event schema is version-sensitive.","Wrap wiki generation so an LLM failure degrades the wiki instead of failing the whole analyze run."],"tags":["opencode","local-llm","cli","empty-response","wiki","json-events"],"backgroundTag":"llm-empty-response","analyzedSha":"52924ef12c2290ceee4612526a828ec4cdf2047f","analyzedAt":"2026-08-20T23:29:22.980Z","contentChangedAt":"2026-08-20T23:29:22.980Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}