abhigyanpatwari/GitNexus · error · Error

OpenCode CLI returned no text output

Error message

OpenCode CLI returned no text output

What it means

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.

Source

Thrown at gitnexus/src/core/wiki/local-cli-client.ts:217

    if (event.type === 'error') {
      const message =
        event.error?.data?.message ||
        event.error?.name ||
        event.message ||
        event.part?.text ||
        line;
      throw new Error(`OpenCode CLI returned error event: ${message}`);
    }

    if (event.type === 'text' && typeof event.part?.text === 'string') {
      textParts.push(event.part.text);
    }
  }

  const content = textParts.join('').trim();
  if (!content) {
    throw new Error('OpenCode CLI returned no text output');
  }
  return content;
}

function buildChildEnv(provider: LocalAgentProvider): NodeJS.ProcessEnv {
  const env: NodeJS.ProcessEnv = {
    ...process.env,
    CI: '1',
  };

  if (provider === 'opencode') {
    delete env.OPENCODE_SERVER_PASSWORD;
    delete env.OPENCODE_SERVER_USERNAME;
  }

  return env;
}

View on GitHub (pinned to 52924ef12c)

Solutions

  1. 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.
  2. 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.
  3. Align versions: update opencode (and GitNexus) so the `--format json` event schema matches what local-cli-client.ts parses.
  4. If the model reliably returns no text parts, switch the wiki generator to a different LocalAgentProvider or disable local-LLM wiki generation.
  5. Report the captured stdout JSON events in a GitNexus issue if a text-bearing event shape is present but unrecognized.

Example fix

// before: model not pinned / not authenticated
gitnexus wiki generate --provider opencode
// → Error: OpenCode CLI returned no text output

// after: verify auth, pin a known-good model, then retry
opencode auth login
opencode run --format json "say ok"   # confirm a text part is emitted
# gitnexus config (wiki generation)
{ "provider": "opencode", "model": "anthropic/claude-sonnet-4-5" }
gitnexus wiki generate --provider opencode
Defensive patterns

Strategy: fallback

Validate before calling

// Preflight: confirm the CLI produces text parts before relying on it
import { execFile } from 'node:child_process';
import { promisify } from 'node:util';
const run = promisify(execFile);

async function opencodeProducesText(dir: string): Promise<boolean> {
  try {
    const { stdout } = await run('opencode', ['run', '--format', 'json', '--dir', dir, 'Reply with: ok'], { timeout: 60_000 });
    return stdout.split('\n').some((l) => {
      try { const e = JSON.parse(l); return e.type === 'text' && typeof e.part?.text === 'string' && e.part.text.trim(); }
      catch { return false; }
    });
  } catch { return false; }
}

Type guard

const isTextPartEvent = (
  e: unknown,
): e is { type: 'text'; part: { text: string } } =>
  typeof e === 'object' && e !== null &&
  (e as { type?: unknown }).type === 'text' &&
  typeof (e as { part?: { text?: unknown } }).part?.text === 'string';

Try / catch

try {
  const res = await callOpenCodeLLM(prompt, config, systemPrompt);
} catch (err) {
  if (err instanceof Error && err.message === 'OpenCode CLI returned no text output') {
    // empty-but-successful run: log events, switch provider or model, do not blind-retry the same setup
    logger.warn('opencode returned no text; falling back', { model: config.model });
    return callCodexLLM(prompt, config, systemPrompt); // or mark wiki section as skipped
  }
  throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of abhigyanpatwari/GitNexus@52924ef12c (2026-08-20). Data as JSON: /api/errors/664017fb41df7f04. Report an issue: GitHub.