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
- 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').
- 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.
- If you are constructing the spec programmatically (e.g. in generate_golden_spec), build issue_id with f"{owner}/{repo}#{issue_number}" before validation.
- 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
- Always construct issue_id with f"{owner}/{repo}#{issue_number}" rather than relying on the LLM to format it.
- Add a pytest case asserting validate_triage_result accepts a well-formed OK payload and rejects malformed issue_ids.
- Log the workable_spec dict before validation during eval runs to catch format drift early.
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
- ${errorMessages.join('\n')}\nPlease fix the configuration fi
- Validation failed: ${formatZodError(result.error, 'Agent Def
- Firestore document ID could not be resolved. Please set the
- Triage execution failed: {raw_output}
- Invalid taskId: ${taskId}
AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12).
Data as JSON: /api/errors/c2884ca31a24639f.
Report an issue: GitHub.