google-gemini/gemini-cli · error · ValueError

Invalid or missing 'issue_id' format: {issue_id}

Error message

Invalid or missing 'issue_id' format: {issue_id}

What it means

This ValueError is thrown by validate_triage_result() when the LLM triage output declares quality='OK' but the workable_spec.issue_id field does not match the required 'owner/repo#number' regex pattern (^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+#[0-9]+$). The validator runs after json.loads on the triage result to enforce structural correctness of the workable spec before it is persisted or judged. It is a schema-integrity guard, not an I/O failure.

Source

Thrown at tools/caretaker-agent/cloudrun/triage-worker/utils/validator.py:82

    if metadata.get("quality") == "OK":
        effort = metadata.get("effort_estimate")
        if effort not in ["SMALL", "MEDIUM", "LARGE"]:
            raise ValueError(
                f"Invalid or missing 'effort_estimate': {effort}"
            )

        spec = data.get("workable_spec")
        if not isinstance(spec, dict):
            raise ValueError("Missing 'workable_spec'")
        
        issue_id = spec.get("issue_id")
        pattern = r"^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+#[0-9]+$"
        valid_id = isinstance(issue_id, str) and bool(
            re.match(pattern, issue_id)
        )
        if not valid_id:
            raise ValueError(
                f"Invalid or missing 'issue_id' format: {issue_id}"
            )

        _assert_section_schema(spec, "summary", {
            "problem": str,
            "root_cause": str,
            "context": str,
        })
        _assert_section_schema(spec, "implementation_plan", {
            "files_to_modify": [str],
            "steps": [str],
        })
        _assert_section_schema(spec, "testing_strategy", {
            "test_file": str,
            "expected_behavior": str,
            "verification_steps": [str],
            "framework": str,
        })

View on GitHub (pinned to 5024443c72)

Solutions

  1. Inspect the full workable_spec dict in the triage output and confirm issue_id is present as a string in 'owner/repo#NNN' form (e.g. 'facebook/react#28052').
  2. If the LLM is producing a malformed id, update the triage system prompt / instructions to enforce the exact issue_id format with examples, then re-run the triage.
  3. If you are constructing the spec programmatically (e.g. in generate_golden_spec), build issue_id with f"{owner}/{repo}#{issue_number}" before validation.
  4. Add a unit test that feeds a quality='OK' payload through validate_triage_result to catch regressions in the issue_id format.

Example fix

// before
workable_spec = {"issue_id": "28052", ...}
// after
workable_spec = {"issue_id": f"{owner}/{repo}#{issue_number}", ...}
Defensive patterns

Strategy: validation

Validate before calling

import re

def is_valid_issue_id(owner: str, repo: str, issue_number: int) -> bool:
    candidate = f"{owner}/{repo}#{issue_number}"
    return bool(re.match(r"^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+#[0-9]+$", candidate))

# Before calling validate_triage_result, build and check:
# spec['issue_id'] = f"{owner}/{repo}#{issue_number}"

Type guard

from typing import Any

def has_valid_issue_id(spec: Any) -> bool:
    if not isinstance(spec, dict):
        return False
    issue_id = spec.get('issue_id')
    if not isinstance(issue_id, str):
        return False
    import re
    return bool(re.match(r"^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+#[0-9]+$", issue_id))

Try / catch

try:
    validate_triage_result(data)
except ValueError as e:
    if 'issue_id' in str(e):
        data.setdefault('workable_spec', {})['issue_id'] = f"{owner}/{repo}#{issue_number}"
        validate_triage_result(data)
    else:
        raise

Prevention

When it happens

Trigger: Called inside validate_triage_result(data) when data['triage_metadata']['quality'] == 'OK'. The spec = data.get('workable_spec') is a dict but spec.get('issue_id') is either None, a non-string type, or a string that omits the '#', the '/', or uses disallowed characters (e.g. spaces, 'owner/repo', '12345', 'owner repo#5', 'owner/repo#abc').

Common situations: The triage LLM hallucinates a numeric-only or URL-style issue_id instead of the slug format. A prompt or model regression causes the agent to emit the issue_id under a different key (e.g. 'issueId'). The spec was hand-crafted or generated by generate_golden_spec and the issue_id field was left out or malformed during JSON synthesis.

Related errors


AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12). Data as JSON: /api/errors/c2884ca31a24639f. Report an issue: GitHub.