Skip to content

InvalidObjectiveError when sending messages with oh-my-openagent plugin (v4.19.3) #39533

Description

@Bearmancer

Bug Report: InvalidObjectiveError when sending messages with oh-my-openagent plugin

Description

When using OpenCode with the oh-my-openagent plugin (v4.19.3), any message sent triggers InvalidObjectiveError: Objective exceeds maximum length of 2000 characters, completely blocking message sending. This occurs even for short messages like "hello" or single slash commands like /ulw-plan.

Root cause: The handleGoalMessage function in oh-my-openagent extracts text from output.parts AFTER keywordDetector and hephaestusAgentsMdInjector hooks have injected large amounts of content (skill instructions, AGENTS.md content, system reminders) into the user's message. When this combined text (injected content + original user message) exceeds 2000 characters, the error is thrown before the message can be sent.

Why opening a new terminal tab fixes it: The injected messages are only added once per session (tracked by injectedSessions Set in hephaestusAgentsMdInjector and defaultModeUltraworkInjectedSessions in keywordDetector). New tab = new session = no prior injections = shorter text.

Impact:

  • Cannot send any messages in existing sessions after first injection
  • Slash commands like /ulw-plan, /caveman fail to execute
  • Forces users to constantly open new terminal tabs to continue working
  • Makes the plugin unusable for extended sessions

Plugins

  • oh-my-openagent v4.19.3 (installed via bunx oh-my-openagent@latest)

OpenCode version

1.18.9

Steps to reproduce

  1. Install oh-my-openagent: bunx oh-my-openagent@latest
  2. Configure OpenCode to use the plugin in opencode.jsonc:
    {
      "plugin": {
        "oh-my-openagent": "^4.19.3"
      }
    }
  3. Start OpenCode in a Windows Terminal tab
  4. Type any message (e.g., "hello", "/ulw-plan", or even press Enter in a new chat)
  5. Observe error: InvalidObjectiveError: Objective exceeds maximum length of 2000 characters
  6. Open a new terminal tab and start OpenCode again
  7. Message sends successfully (first message only)
  8. Subsequent messages in the same session fail with the same error

Expected behavior: Messages should send successfully regardless of injected content from hooks.

Actual behavior: Error is thrown because handleGoalMessage validates the combined text (injected content + user message) instead of just the user's original input.

Technical Analysis

Error Location

at validateObjective (oh-my-openagent/dist/index.js:106852:36)
at setGoal (oh-my-openagent/dist/index.js:106881:42)
at handleGoalMessage (oh-my-openagent/dist/index.js:169443:26)
at <anonymous> (oh-my-openagent/dist/index.js:169715:22)
at SessionPrompt.createUserMessage (chunk-58s0h5f2.js:1085:9954)

Root Cause Flow

  1. User types message (e.g., "hello" or "/ulw-plan")
  2. createChatMessageHandler3 is called with (input, output) at line 169676
  3. nativeGoalCommand = consumeNativeGoalCommandMarker(output.parts) is executed at line 169681
  4. runChatMessageHooks runs (lines 169707-169712), which includes:
    • keywordDetector hook (line 169668) - injects skill messages into output.parts[0].text
    • hephaestusAgentsMdInjector hook (line 169674) - injects AGENTS.md content for Hephaestus agent
  5. handleGoalMessage is called at line 169715
  6. extractPromptText5(output.parts) extracts the combined text (injected messages + original user text)
  7. If combined text > 2000 chars → InvalidObjectiveError is thrown

Code Evidence

keywordDetector hook (lines 105301-105314):

const textPartIndex = output.parts.findIndex(isRealUserTextPart);
if (textPartIndex === -1) {
  log2(`[keyword-detector] No text part found, skipping injection`, { sessionID: input.sessionID });
  return;
}
const allMessages = detectedKeywords.map((k) => k.message).join(`\n\n`);
const originalText = output.parts[textPartIndex].text ?? "";
output.parts[textPartIndex].text = `${allMessages}\n\n---\n\n${originalText}`;

hephaestusAgentsMdInjector hook (lines 107170-107195):

const textPart = output.parts.find(isRealUserTextPart);
if (!textPart) return;
const agentsPaths = await findAgentsMdUp({...});
if (agentsPaths.length === 0) return;
const contextBlocks = [];
for (const agentsPath of agentsPaths) {
  const content = await fsPromises2.readFile(agentsPath, "utf-8");
  const { result, truncated } = await truncator.truncate(input.sessionID, content);
  contextBlocks.push(formatAgentsMdContextBlock({ agentsPath, content: result, truncated }));
}
textPart.text = `${contextBlocks.join("")}\n\n---\n\n${textPart.text ?? ""}`;
injectedSessions.add(input.sessionID);

handleGoalMessage (lines 169434-169443):

function handleGoalMessage(args) {
  const { hooks: hooks2, input, output, isFirstMessage, pluginConfig, nativeGoalCommand } = args;
  if (!hooks2.goal || nativeGoalCommand) {
    return;
  }
  const promptText = extractPromptText5(output.parts);  // Extracts COMBINED text
  const parsed = parseGoalCommand(promptText);
  switch (parsed.kind) {
    case "setObjective":
      const result = setGoal({ directory, sessionID: input.sessionID }, parsed.objective);
      // validateObjective throws if objective > 2000 chars

Log Evidence (Last 6 Hours)

Error frequency: 42 occurrences of InvalidObjectiveError across 15+ sessions

Recent errors (from 09:36 to 15:08):

timestamp=2026-07-29T15:02:48.157Z level=ERROR run=b040f142 message="prompt_async failed" sessionID=ses_05399d8ccffeTkE5RUHSrqhL3L cause="Cause([Die(InvalidObjectiveError: Objective exceeds maximum length of 2000 characters)])"

timestamp=2026-07-29T15:02:57.594Z level=ERROR run=b040f142 message=failed ref=err_20b94be3 error="InvalidObjectiveError: Objective exceeds maximum length of 2000 characters" cause="..."

timestamp=2026-07-29T15:05:48.417Z level=ERROR run=ec94e084 message="prompt_async failed" sessionID=ses_05315b069ffeRtvFuSwY9KhRNt cause="Cause([Die(InvalidObjectiveError: Objective exceeds maximum length of 2000 characters)])"

timestamp=2026-07-29T15:08:41.670Z level=ERROR run=ec94e084 message="prompt_async failed" sessionID=ses_0581fab26ffeiSMYmppLdFBPdU cause="Cause([Die(InvalidObjectiveError: Objective exceeds maximum length of 2000 characters)])"

Error pattern:

  • First message in a session succeeds (no prior injections)
  • Subsequent messages fail (hooks have injected content)
  • Opening a new terminal tab resets the session state
  • The error occurs regardless of message length (even "hello" fails)

Proposed Fix

Option 1: Fix in handleGoalMessage (Recommended)
Extract original user text BEFORE runChatMessageHooks modifies it:

// At line 169680, BEFORE runChatMessageHooks:
const originalPromptText = extractPromptText5(output.parts);

// At line 169715, pass original text:
handleGoalMessage({
  hooks: hooks2,
  input,
  output,
  isFirstMessage,
  pluginConfig,
  nativeGoalCommand,
  originalPromptText  // Pass original text for validation
});

Then in handleGoalMessage:

function handleGoalMessage(args) {
  const { hooks: hooks2, input, output, isFirstMessage, pluginConfig, nativeGoalCommand, originalPromptText } = args;
  if (!hooks2.goal || nativeGoalCommand) {
    return;
  }
  const promptText = originalPromptText ?? extractPromptText5(output.parts);
  const parsed = parseGoalCommand(promptText);
  // ... rest of function
}

Option 2: Increase 2000 char limit
Quick fix but doesn't address root cause. Could mask other issues.

Option 3: Mark injected content as synthetic
Prevent extractPromptText5 from including it. Requires changes to injection hooks.

Option 4: Disable goal feature for non-goal messages
Check if message is a slash command before validating. Already partially done with nativeGoalCommand flag but doesn't work for all cases.

Environment Details

  • OS: Windows 11 (Build 26300.0)
  • Terminal: Windows Terminal
  • Shell: PowerShell 7+
  • OpenCode: 1.18.9
  • oh-my-openagent: 4.19.3
  • Plugin installation: bunx oh-my-openagent@latest
  • Plugin config location: C:\Users\Lance\.config\opencode\opencode.jsonc

Additional Context

  • bunx oh-my-openagent doctor reports no issues
  • The issue persists across OpenCode restarts
  • Only resolved by opening a new terminal tab (new session)
  • Affects all slash commands (/ulw-plan, /caveman, etc.)
  • Affects regular messages regardless of length
  • The issue is specific to oh-my-openagent's goal handling, not OpenCode core

Screenshot and/or share link

Run /share in OpenCode to get a share link, or attach screenshots showing:

  1. The error message in the terminal
  2. The successful message after opening a new terminal tab
  3. The log file showing repeated InvalidObjectiveError entries

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions