shareAI-lab/learn-claude-code · error · GoalError

goal condition cannot exceed {MAX_GOAL_LENGTH} characters

Error message

goal condition cannot exceed {MAX_GOAL_LENGTH} characters

What it means

set_goal rejects conditions longer than MAX_GOAL_LENGTH = 4000 characters (s17_goal_loop/code.py:287). The condition is embedded in the evaluator's prompt each turn, so an oversized condition bloats every evaluation call; the hard cap keeps the evaluator prompt bounded and its verdicts reliable.

Source

Thrown at s17_goal_loop/code.py:287

    ):
        if block_cap < 1:
            raise GoalError("block_cap must be at least 1")
        self.evaluator = evaluator
        self.block_cap = block_cap
        self.events = events if events is not None else []
        self.active: GoalState | None = None
        self.last_status: dict[str, Any] | None = None
        self.consecutive_blocks = 0

    def begin_query(self) -> None:
        self.consecutive_blocks = 0

    def set_goal(self, condition: str, tokens_at_start: int = 0) -> GoalState:
        condition = condition.strip()
        if not condition:
            raise GoalError("goal condition cannot be empty")
        if len(condition) > MAX_GOAL_LENGTH:
            raise GoalError(
                f"goal condition cannot exceed {MAX_GOAL_LENGTH} characters"
            )
        if self.active is not None:
            self._record(
                active=False,
                met=False,
                failed=False,
                reason="replaced by a new goal",
            )
        self.active = GoalState(
            condition=condition,
            iterations=0,
            set_at=time.time(),
            tokens_at_start=tokens_at_start,
        )
        self.consecutive_blocks = 0
        self._record(active=True, met=False, failed=False, reason="goal set")
        return self.active

View on GitHub (pinned to 985456f4ad)

Solutions

  1. Distill the condition to a single verifiable predicate (one or two sentences)
  2. Split a large spec into the transcript (user message) and keep only the success criterion as the goal
  3. If a longer cap is genuinely needed, raise MAX_GOAL_LENGTH deliberately — but prefer trimming the condition

Example fix

# before
session.goal.set_goal(open("SPEC.md").read())

# after
session.goal.set_goal("SPEC.md: every requirement in the spec is implemented and tests/test_spec.py passes")
Defensive patterns

Strategy: validation

Validate before calling

MAX_GOAL_LENGTH = 4000
condition = goal_text.strip()
if len(condition) > MAX_GOAL_LENGTH:
    raise SystemExit(f"goal must be at most {MAX_GOAL_LENGTH} chars (got {len(condition)})")
controller.set_goal(condition)

Type guard

def is_within_goal_limit(condition: str) -> bool:
    return 0 < len(condition.strip()) <= 4000

Try / catch

try:
    controller.set_goal(condition)
except GoalError as error:
    if "cannot exceed" in str(error):
        condition = summarize(condition)  # distill to the success predicate
        controller.set_goal(condition)
    else:
        raise

Prevention

When it happens

Trigger: Calling set_goal with a condition over 4000 chars after stripping — e.g. pasting an entire spec document, a full file's contents, or a long transcript excerpt as the 'goal'.

Common situations: Using the goal field to smuggle context/instructions instead of a concise success predicate; programmatically generating the goal from a template that grows unbounded; concatenating many acceptance criteria into one string.

Related errors


AI-assisted analysis of shareAI-lab/learn-claude-code@985456f4ad (2026-08-14). Data as JSON: /api/errors/445d23b4c03639dd. Report an issue: GitHub.