Repository navigation
MCPG step fails with docker: invalid reference format. — extra \ \ after -e ADO_MCP_AUTH_TOKEN in generated YAML (v0.36.0) #1034
Description
Summary
Compiled pipelines that use the built-in azure-devops MCP tool fail at the Start MCP Gateway (MCPG) step with docker: invalid reference format. The MCPG container never starts, the /health poll loop runs out, and the Agent job exits 1 (Bash exited with code '1').
Root cause: start_mcpg_step in src/compile/agentic_pipeline.rs double-appends a \ line continuation to the docker-env flag emitted by generate_mcpg_docker_env. The emitted YAML contains a literal \ \ token, which bash interprets as a one-character argument (a single space) inserted between -e ADO_MCP_AUTH_TOKEN=… and the image, so docker run consumes that space as the image reference.
Affects: every agent whose front matter declares tools.azure-devops (or anything else that contributes an extension pipeline_env mapping). In our repository this took down five pipelines simultaneously after a routine ado-aw compile upgrade to v0.36.0.
Observed Run
- Build: https://dev.azure.com/msazuresphere/4x4/_build/results?buildId=613512
- Definition:
ado-aw reviewer(compiled fromagents/pr-reviewer.md) - Source branch:
refs/heads/jamesadevine/test-pr-reviewer-bait - Result:
failedafter 2m 25s - Failed step: Start MCP Gateway (MCPG) (timeline record
691d60ec-3d15-5b34-11ae-186526790c53, task log 43) - Compiler version:
ado-aw 0.36.0(verified viaado-aw --version;aw_info.json.compiler_version = "0.36.0") - MCPG image:
ghcr.io/github/gh-aw-mcpg:v0.3.25
Failing step log (verbatim, lines 51-55)
2026-06-15T20:17:15.6783133Z MCPG started (PID: 2650)
2026-06-15T20:17:15.6949924Z docker: invalid reference format.
2026-06-15T20:17:15.6951878Z See 'docker run --help'.
2026-06-15T20:17:45.9518262Z
2026-06-15T20:17:45.9535713Z ##[error]Bash exited with code '1'.
(The 30s gap is the /health poll that times out because the docker container never started.)
ado-aw audit 613512 --json corroborates: mcpg/stderr.log contains exactly two lines — docker: invalid reference format. / See 'docker run --help'. — and safe_outputs.ndjson is empty (the agent never ran).
Generated YAML (pr-reviewer.yml, lines 475-486)
echo "$MCPG_CONFIG" | docker run -i --rm \
--name mcpg \
--network host \
--entrypoint /app/awmg \
-v /var/run/docker.sock:/var/run/docker.sock \
-e MCP_GATEWAY_PORT="$(MCP_GATEWAY_PORT)" \
-e MCP_GATEWAY_DOMAIN="$(MCP_GATEWAY_DOMAIN)" \
-e MCP_GATEWAY_API_KEY="$(MCP_GATEWAY_API_KEY)" \
-e ADO_MCP_AUTH_TOKEN="$SC_READ_TOKEN" \ \ # ← BUG: trailing "\ \"
ghcr.io/github/gh-aw-mcpg:v0.3.25 \
--routed --listen 0.0.0.0:80 --config-stdin --log-dir /tmp/gh-aw/mcp-logs \
> "$GATEWAY_OUTPUT" 2> >(tee /tmp/gh-aw/mcp-logs/stderr.log >&2) &In bash, \ is an escaped space (literal space character treated as part of an argument) and \<NL> is a line continuation. Sequence \ \<NL> therefore produces:
- a one-character argument consisting of a single space, then
- the line continuation.
docker run’s positional-argument parser scans for the first non-option token and treats it as IMAGE. That token is " " (a single space) — an invalid reference. The actual ghcr.io/github/gh-aw-mcpg:v0.3.25 is then parsed as the COMMAND.
Removing the stray space-escape (i.e. just -e ADO_MCP_AUTH_TOKEN="$SC_READ_TOKEN" \) makes the docker invocation valid again.
Root cause in ado-aw
The duplication happens in start_mcpg_step (src/compile/agentic_pipeline.rs, ~lines 1334-1369 in v0.36.0). It reads the value returned by generate_mcpg_docker_env and re-wraps every line:
// src/compile/agentic_pipeline.rs (v0.36.0)
let docker_env_lines: String =
if mcpg_docker_env.trim().is_empty() || mcpg_docker_env.trim() == "\\" {
"\\\n \\".to_string()
} else {
mcpg_docker_env
.lines()
.map(|l| format!("{l} \\")) // <-- appends ` \` to every line
.collect::<Vec<_>>()
.join("\n ")
};But generate_mcpg_docker_env (src/compile/common.rs, ~lines 2034-2092) already appends a trailing \ to its returned string:
// src/compile/common.rs (v0.36.0)
env_flags.sort();
if env_flags.is_empty() {
"\\".to_string()
} else {
let flags = env_flags.join(" \\\n");
format!("{} \\", flags) // <-- already ends with ` \`
}So for a single-entry input (-e ADO_MCP_AUTH_TOKEN="$SC_READ_TOKEN" \), .lines() yields one line ending in \, and format!("{l} \\") appends a second \ → -e ADO_MCP_AUTH_TOKEN="$SC_READ_TOKEN" \ \.
For multi-entry inputs the same defect would corrupt only the last flag, but in the common ADO-tool case there’s exactly one extension-contributed flag, so this is the line that breaks.
Reproduction
Minimal agent.md:
---
name: repro
description: repro
on:
workflow_dispatch:
permissions:
read: any-arm-service-connection
tools:
azure-devops:
toolsets:
- repos
safe-outputs:
add-pr-comment:
max: 1
---
Stub.ado-aw compile agent.md
grep -n 'ADO_MCP_AUTH_TOKEN' agent.yml
# → -e ADO_MCP_AUTH_TOKEN="$SC_READ_TOKEN" \ \
Run on Azure DevOps → MCPG step fails with docker: invalid reference format.
Impact
- All compiled pipelines that include the ADO MCP tool with
permissions.readagainst an ARM service connection are unrunnable onado-aw 0.36.0. - In this repository, 5 of 5 such pipelines are affected:
ctf.yml:470,dotnet-dependency-updater.yml:392,pr-reviewer.yml:483,release-readiness.yml:464,test-pr-reviewer-bait.yml:459— each ending in-e ADO_MCP_AUTH_TOKEN="$SC_READ_TOKEN" \ \. - The Agent job runs for the full
/healthtimeout (30s) before failing, wasting build minutes and obscuring the root cause behind a genericBash exited with code '1'. - The MD-source markdown is unchanged from a working
ado-aw 0.35.xbuild; only recompiling under v0.36.0 introduced the bad output.
Suggested fix direction
Either:
- Have
generate_mcpg_docker_envreturn the env flags without the trailing\(let the caller own continuations), or - Drop the
format!("{l} \\")line wrap instart_mcpg_stepand just.join("\n ")the already-terminated lines.
A regression test that compiles a minimal agent with an ADO tool + ARM service connection and asserts the emitted YAML never contains the literal substring \ \ (or, more strictly, runs bash -n against the rendered step body) would prevent reintroduction.
Diagnostic artifacts
aw_info.json:{"compiler_version":"0.36.0","engine":"copilot","model":"claude-opus-4.7","source":"agents/pr-reviewer.md","target":"standalone"}mcpg-config.json(sanitized): standard ADO MCP entry (container: node:20-slim,entrypoint: npx, args-y @azure-devops/mcp msazuresphere -d repos -a envvar) + HTTP safeoutputs entry.audit-613512.json(overview): Setupsucceeded(26s), Agentfailed(1m38s), no Detection / SafeOutputs jobs scheduled because Agent stage failed.- Full step log: https://dev.azure.com/msazuresphere/4881b890-93a9-4bcf-95c9-d07c192a073a/_apis/build/builds/613512/logs/43
Activity