Skip to content

Conversation

@well0nez
Copy link

@well0nez well0nez commented Feb 10, 2026

Summary

MCP tools may not return output.output as a string, causing a TypeError when calling .toLowerCase() on it.

Error: TypeError: undefined is not an object (evaluating 'output.output.toLowerCase')

This happens when using MCP servers like ida-pro-mcp where the tool output format differs from standard OpenCode tools.

Changes

  • Added guard in edit-error-recovery/hook.ts to check if output.output exists and is a string before calling string methods
  • Added guard in comment-checker/hook.ts with the same protection

Files Changed

  • src/hooks/edit-error-recovery/hook.ts
  • src/hooks/comment-checker/hook.ts

Testing

Tested with ida-pro-mcp MCP server - the error no longer occurs and MCP tools work correctly.


Summary by cubic

Prevent crashes in tool.execute.after hooks by guarding against undefined or non-string output.output before calling .toLowerCase(). Fixes TypeErrors with MCP servers like ida-pro-mcp and keeps tool execution stable.

Written for commit b282697. Summary will update on new commits.

MCP tools may not return output.output as a string, causing TypeError when
calling .toLowerCase(). This fix adds a guard to check if output.output
exists and is a string before attempting to call string methods on it.

Fixes crash: TypeError: undefined is not an object (evaluating 'output.output.toLowerCase')
@github-actions
Copy link
Contributor

Thank you for your contribution! Before we can merge this PR, we need you to sign our Contributor License Agreement (CLA).

To sign the CLA, please comment on this PR with:

I have read the CLA Document and I hereby sign the CLA

This is a one-time requirement. Once signed, all your future contributions will be automatically accepted.


I have read the CLA Document and I hereby sign the CLA


well0nez seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

@well0nez
Copy link
Author

I have read the CLA Document and I hereby sign the CLA

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Auto-approved: The changes add guards against undefined output values, reducing potential errors; no regressions detected and criteria are fully met.

@mathew-cf
Copy link

Please merge soon :)
I know a few folks whose MCP use is having issues because of this.

@NikkeTryHard
Copy link

NikkeTryHard commented Feb 11, 2026

Full Audit: output.output Access in tool.execute.after Hooks

After auditing the source, this PR fixes 2 of 4 hooks that crash on MCP tool results. There are also 7 hooks with a silent corruption pattern.

Hard Crashes (TypeError)

# Hook File Line Pattern PR #1735
1 comment-checker hook.ts L95 output.output.toLowerCase() Fixed
2 edit-error-recovery hook.ts L47 output.output.toLowerCase() Fixed
3 task-resume-info hook.ts L24-27 .startsWith(), .includes(), .trimEnd() Missing
4 delegate-task-retry hook.ts L14 Passed to detectDelegateTaskError() which calls .includes() at patterns.ts:65 Missing

The same one-liner used in this PR resolves all four:

if (!output.output || typeof output.output !== "string") return

Silent Corruption (undefined += "string" = "undefinedstring")

These hooks append to output.output without checking its type. When output.output is undefined, JavaScript coerces it to the string "undefined" and concatenates, producing corrupted output like "undefinedRemember to use...":

Hook File Line
agent-usage-reminder hook.ts L80
task-reminder hook.ts L42
category-skill-reminder hook.ts L109
context-window-monitor hook.ts L77
rules-injector injector.ts L119
directory-agents-injector injector.ts L49
directory-readme-injector injector.ts L49

These won't crash, but they produce garbage output for MCP tools. A guard like if (typeof output.output !== "string") return or changing output.output += to output.output = (output.output ?? "") + would fix them.

Already-Safe Hooks (for reference)

tool-output-truncator, empty-task-response-detector, atlas/tool-execute-after, interactive-bash-session, and claude-code-hooks/tool-execute-after-handler all have proper guards (typeof checks, optional chaining, or falsy guards).

Root Cause

Since ai@6.0.0 (Dec 22, 2025), ToolResultPart.output is no longer the raw tool result. It is now wrapped by createToolModelOutput() (introduced in vercel/ai#6784) into a ToolResultOutput envelope:

Before: output.output → "some string"          (raw tool result)
After:  output.output → { type: "text", value: "some string" }

The hooks expect the old shape. For MCP tools specifically, output.output resolves to undefined because the envelope object has no .output property — only .type and .value. Built-in tools are unaffected because OpenCode's prompt.ts wraps their results into { output: string, title: string, metadata: object } before the SDK transforms them.

Related

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants