google-gemini/gemini-cli · error · Error
Invalid syntax${contextInfo}: Unclosed injection starting at
Error message
Invalid syntax${contextInfo}: Unclosed injection starting at index ${startIndex} ('${trigger}'). Ensure braces are balanced. Paths or commands with unbalanced braces are not supported directly. What it means
Thrown by extractInjections() when a trigger sequence (e.g. '!{' for shell or '@{' for includes) is found but brace counting never returns to zero before the end of the string — i.e. the injection is unclosed. The parser does simple brace counting and has no escape mechanism, so unbalanced braces inside the content also trigger it.
Source
Thrown at packages/cli/src/services/prompt-processors/injectionParser.ts:82
injections.push({
content: injectionContent.trim(),
startIndex,
endIndex,
});
index = endIndex;
foundEnd = true;
break;
}
}
currentIndex++;
}
// Check if the inner loop finished without finding the closing brace.
if (!foundEnd) {
const contextInfo = contextName ? ` in command '${contextName}'` : '';
// Enforce strict parsing (Comment 1) and clarify limitations (Comment 2).
throw new Error(
`Invalid syntax${contextInfo}: Unclosed injection starting at index ${startIndex} ('${trigger}'). Ensure braces are balanced. Paths or commands with unbalanced braces are not supported directly.`,
);
}
}
return injections;
}
View on GitHub (pinned to 5024443c72)
Solutions
- Add the missing closing '}' so braces are balanced around the injection.
- If the command needs literal braces, wrap the whole command in balanced outer braces (e.g. '!{ sh -c "..." }') or avoid braces in the embedded command.
- Move brace-heavy logic into a script file invoked without inline braces.
Example fix
// before
Summarize !{awk '{print $1}' file.txt} output
// after
Summarize !{awk "{print \$1}" file.txt} output
// or simpler: avoid inline braces
Summarize !{./first-col.sh file.txt} output Defensive patterns
Strategy: validation
Validate before calling
function injectionsAreClosed(prompt: string, trigger: string): boolean {
let i = 0;
while (i < prompt.length) {
const start = prompt.indexOf(trigger, i);
if (start === -1) break;
let j = start + trigger.length, depth = 1;
for (; j < prompt.length && depth > 0; j++) {
if (prompt[j] === '{') depth++;
else if (prompt[j] === '}') depth--;
}
if (depth !== 0) return false;
i = j;
}
return true;
}
if (!injectionsAreClosed(prompt, '!{')) throw new Error('Unbalanced !{...} braces'); Type guard
function isBalancedInjection(prompt: string, trigger: string): boolean {
return injectionsAreClosed(prompt, trigger);
} Try / catch
try {
extractInjections(prompt, '!{', cmdName);
} catch (e) {
if (e instanceof Error && /Unclosed injection/.test(e.message)) {
// fix the unbalanced braces, then retry
}
throw e;
} Prevention
- Always close '!{...}' and '@{...}' with a matching '}'.
- Avoid literal unbalanced braces inside injected commands; wrap them in balanced outer braces or use a script.
- Lint prompts containing injections before submission.
When it happens
Trigger: A prompt contains '!{echo hi' with no matching '}', or a command/path inside the braces itself contains an unmatched '{' or '}', so braceCount never reaches 0.
Common situations: Forgot the closing brace on a shell injection; used a command containing literal braces (awk, find -exec, JSON via echo); pasted a path with a stray brace.
Related errors
- Security configuration not loaded. Cannot verify shell comma
- Failed to start shell command in '${this.commandName}': ${ex
- Exiting due to a confirmation prompt requested by the comman
- ${this.commandName} cannot be run. Blocked command: "${comma
- Shell command confirmation required
AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12).
Data as JSON: /api/errors/cd1f535b4db813f0.
Report an issue: GitHub.