can1357/oh-my-pi · error

result cannot contain both data and error

Error message

result cannot contain both data and error

What it means

The yield tool for subagent results rejects a submission that supplies both `data` (success payload) and `error` (failure message) at once. A result is either a success or a failure — including both is ambiguous, so execute() throws early instead of guessing. The tool schema should already prevent this, but direct calls or malformed tool args can slip past validation.

Source

Thrown at packages/coding-agent/src/tools/yield.ts:382

		_context?: AgentToolContext,
	): Promise<AgentToolResult<YieldDetails>> {
		const raw = params as Record<string, unknown>;
		const yieldType = parseYieldType(raw.type);
		const resultRecord = resolveResultRecord(raw, yieldType);
		if (resultRecord === undefined) {
			throw new Error(`result must be an object containing either data or error. ${YIELD_RESULT_FORMAT_HINT}`);
		}
		const errorMessage = typeof resultRecord.error === "string" ? resultRecord.error : undefined;
		let data = resultRecord.data;
		const useLastTurn =
			errorMessage === undefined && data === undefined && yieldType !== undefined && !("error" in resultRecord);
		// Incremental array-typed sections carry partial data (one finding, one
		// field) that cannot satisfy the full output schema; the assembled result
		// is validated as a whole at finalization (executor finalizeSubprocessOutput).
		const isIncremental = Array.isArray(yieldType) && yieldType.length > 0;

		if (errorMessage !== undefined && data !== undefined) {
			throw new Error("result cannot contain both data and error");
		}
		if (errorMessage === undefined && data === undefined && yieldType === undefined) {
			this.#emptyResultFailures++;
			if (this.#emptyResultFailures > MAX_EMPTY_RESULT_RETRIES) {
				const attemptCount = this.#emptyResultFailures;
				this.#emptyResultFailures = 0;
				const error =
					`yield result stayed empty after ${attemptCount} consecutive attempt(s); aborting child instead of retrying forever. ` +
					'Submit success as `{ "result": { "data": <your output> } }` or failure as `{ "result": { "error": "message" } }`.';
				return {
					content: [{ type: "text", text: `Task aborted: ${error}` }],
					details: {
						data: undefined,
						status: "aborted",
						error,
						type: yieldType,
					},
				};

View on GitHub (pinned to 9690622007)

Solutions

  1. Remove the `error` field and submit {result: {data: ...}} for a successful outcome
  2. Remove `data` and submit {result: {error: "message"}} if the task failed
  3. Ensure failed/absent values are `undefined`, not empty strings or placeholder text, so the mutually-exclusive check passes
  4. Fix the tool-call argument construction in the calling harness so it never emits both keys

Example fix

// before
yield({ result: { data: { findings }, error: "none" } });
// after
yield({ result: { data: { findings } } });
Defensive patterns

Strategy: validation

Validate before calling

function canYield(r) { return (r.data === undefined) !== (r.error === undefined); }
if (!canYield(result)) throw new TypeError('yield result must have exactly one of data or error');

Type guard

function isExclusiveResult(r) {
  const hasData = r.data !== undefined;
  const hasError = r.error !== undefined;
  return hasData !== hasError;
}

Try / catch

try {
  yield({ result });
} catch (err) {
  if (err.message.includes('both data and error')) {
    yield({ result: result.error !== undefined ? { error: result.error } : { data: result.data } });
  } else throw err;
}

Prevention

When it happens

Trigger: Calling the yield tool (via result/section/finalize/overrideResult) with both `data` and `error` defined in the result payload, e.g. {result: {data: {...}, error: "something"}}.

Common situations: A model or agent harness copies a result template and forgets to delete the `error` field; a wrapper always sets `error: undefined` but a bug turns it into a string like "none" or "" (non-undefined); hand-crafted RPC/tool-call payloads bypass schema validation.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/f46a622e47922ce6. Report an issue: GitHub.