What happened?
auggie cloud expert apply -f bundle.yaml fails for every ExpertBundle I throw at it — including round-tripping a known-good auggie cloud expert export of an already-deployed expert (Advisor) — with:
Failed to apply expert bundle: HTTP error: 400 Bad Request: Json deserialize error: invalid type: null, expected i32 at line 1 column 310
Request ID: 1fc3ed43-a53b-4773-8841-b700e6b08b2e
The column number shifts with bundle size but the error class is identical. auggie cloud expert validate and auggie cloud expert apply --dry-run both pass — the failure is only on the live POST.
I patched globalThis.fetch from NODE_OPTIONS to log outgoing bodies and the cause is clear. The CLI sends:
{
"scope": 2,
"config": {
"name": "Linear Groomer Diag",
...
"session_config": {
"model": "claude-opus-4-7",
"include_default_system_prompt": true,
"system_prompt": "You are a Linear ticket groomer.",
"visibility": null,
"user_metadata": null,
"auto_cleanup_on_idle": null
},
"vm_config": { "install_git_credentials": true, "install_user_secrets": true, "base_image_id": "<env-uuid>", "clone_repos": [], "resources": { "cpu_cores": 2, "memory_mib": 4096 } },
...
}
}
The three highlighted session_config fields are null. The server's protobuf deserializer expects an i32 enum at session_config.visibility and rejects the request before any of the rest of the body is even considered.
Root cause
The apply path's J7n-equivalent (the YAML-bundle → API-config converter) builds sessionConfig with only three keys:
sessionConfig: {
systemPrompt: r.systemPrompt,
model: o,
includeDefaultSystemPrompt: r.includeDefaultSystemPrompt,
}
…so visibility, userMetadata, and autoCleanupOnIdle are undefined on the JS object. That's correct, and JSON.stringify on its own would drop them.
But Cde (the config → snake_case API serializer) enumerates those keys explicitly:
...t.sessionConfig ? {
session_config: {
model: t.sessionConfig.model,
include_default_system_prompt: t.sessionConfig.includeDefaultSystemPrompt,
system_prompt: t.sessionConfig.systemPrompt,
visibility: t.sessionConfig.visibility, // undefined → null on the wire
user_metadata: t.sessionConfig.userMetadata, // undefined → null on the wire
auto_cleanup_on_idle: t.sessionConfig.autoCleanupOnIdle, // undefined → null on the wire
}
} : {}
Somewhere downstream of Cde (between the UDe.createExpert pass-through and the actual transport — looks like the protobuf-typed apiServer.createCloudExpert codec) those undefined values get materialized as JSON null rather than being omitted. Either the codec needs to skip undefined keys, or Cde needs to spread these conditionally the way it does for cpuCores, snapshotId, etc.:
...t.sessionConfig.visibility !== undefined ? { visibility: t.sessionConfig.visibility } : {},
What did you expect to happen?
auggie cloud expert apply -f bundle.yaml succeeds for any bundle that auggie cloud expert validate and apply --dry-run accept — including the round-trip case of apply-ing a fresh export with no edits. Optional unset fields should be omitted from the request body, not sent as null.
Steps to reproduce
auggie cloud expert init --name diag-test -o /tmp/diag.yaml
- Fill in
spec.expert.environment.id and spec.expert.model: claude-opus-4-7.
auggie cloud expert validate -f /tmp/diag.yaml → passes.
auggie cloud expert apply --dry-run -f /tmp/diag.yaml → passes.
auggie cloud expert apply -f /tmp/diag.yaml → 400, expected i32.
Alternative reproduction (round-trip):
auggie cloud expert export <any-existing-expert-id> -o /tmp/x.yaml
auggie cloud expert apply -f /tmp/x.yaml → same 400.
Workaround
A NODE_OPTIONS=--require=<shim> that strips null-valued keys from POST /cloud-experts/experts/* bodies makes the apply succeed and the resulting expert is well-formed:
const origFetch = globalThis.fetch;
function clean(o) {
if (Array.isArray(o)) return o.map(clean);
if (o && typeof o === 'object') {
const r = {};
for (const [k, v] of Object.entries(o)) if (v !== null) r[k] = clean(v);
return r;
}
return o;
}
globalThis.fetch = async (url, opts) => {
if (opts?.method === 'POST' && opts.body && String(url).includes('/cloud-experts/experts/')) {
try {
opts = { ...opts, body: JSON.stringify(clean(JSON.parse(opts.body))) };
} catch (_) {}
}
return origFetch(url, opts);
};
With the shim, apply succeeds and the expert is created correctly — confirming the server-side schema is fine and the CLI body is the only issue.
Auggie version
999.999.999 (commit b7668abcf77) — this is the build shipping inside Augment Cloud agent VMs (/opt/augment/augment.mjs, symlinked from /usr/local/bin/auggie). I have not verified against the published @augmentcode/auggie 0.24.0; the relevant code (Cde in the bundled augment.mjs) is internal CLI logic so the bug is likely present there too, but worth a quick check.
Request ID
1fc3ed43-a53b-4773-8841-b700e6b08b2e
(Other request IDs from the same session that hit the same error: 377b94f9-d9c6-4a10-bfe8-ff21556a8590, fc74fea3-fd1b-4850-b066-bb45252fea82, 960af909-4cc6-46d1-a0de-e96184402fec, e13887bb-2a81-4a79-a03c-2acc531639cd, 7689da7a-15bd-48a2-9486-c7c28fd59bdd, a46dec8a-bb7d-484f-b185-0f3a353f9145 — round-trip of Advisor export, b08024f3-72a5-4d59-bdf4-90f52d0512b7, 4da66c18-fc1c-4ef0-a39c-3579e22bf740, 11d5a401-57b6-48cf-9c45-3f3b9e44b102.)
Environment details
Environment
- OS: Augment Cloud agent VM (Linux)
- Shell:
sh
- Auggie binary:
/opt/augment/augment.mjs (symlinked from /usr/local/bin/auggie)
- Auggie version:
999.999.999 (commit b7668abcf77)
- Tenant API:
d15.api.augmentcode.com
Anything else we need to know?
The bug is fully blocking auggie cloud expert apply for any tenant on this CLI build — every fresh expert and every round-trip update fails. expert validate / apply --dry-run are happy because the bug is in the request body, not the bundle, so static checks miss it.
The minimal server-side-friendly fix is to spread the three optional session_config keys conditionally in Cde, the same way cpu_cores, memory_mib, snapshot_id, etc. are already handled in the same function. The same probably applies to any other undefined → null enum field — vm_config.image_source and routing_target.daemon_vm_id are already gated correctly; session_config.visibility/user_metadata/auto_cleanup_on_idle are not.
What happened?
auggie cloud expert apply -f bundle.yamlfails for every ExpertBundle I throw at it — including round-tripping a known-goodauggie cloud expert exportof an already-deployed expert (Advisor) — with:The column number shifts with bundle size but the error class is identical.
auggie cloud expert validateandauggie cloud expert apply --dry-runboth pass — the failure is only on the live POST.I patched
globalThis.fetchfromNODE_OPTIONSto log outgoing bodies and the cause is clear. The CLI sends:{ "scope": 2, "config": { "name": "Linear Groomer Diag", ... "session_config": { "model": "claude-opus-4-7", "include_default_system_prompt": true, "system_prompt": "You are a Linear ticket groomer.", "visibility": null, "user_metadata": null, "auto_cleanup_on_idle": null }, "vm_config": { "install_git_credentials": true, "install_user_secrets": true, "base_image_id": "<env-uuid>", "clone_repos": [], "resources": { "cpu_cores": 2, "memory_mib": 4096 } }, ... } }The three highlighted
session_configfields arenull. The server's protobuf deserializer expects ani32enum atsession_config.visibilityand rejects the request before any of the rest of the body is even considered.Root cause
The apply path's
J7n-equivalent (the YAML-bundle → API-config converter) buildssessionConfigwith only three keys:…so
visibility,userMetadata, andautoCleanupOnIdleareundefinedon the JS object. That's correct, andJSON.stringifyon its own would drop them.But
Cde(theconfig→ snake_case API serializer) enumerates those keys explicitly:Somewhere downstream of
Cde(between theUDe.createExpertpass-through and the actual transport — looks like the protobuf-typedapiServer.createCloudExpertcodec) thoseundefinedvalues get materialized as JSONnullrather than being omitted. Either the codec needs to skip undefined keys, orCdeneeds to spread these conditionally the way it does forcpuCores,snapshotId, etc.:What did you expect to happen?
auggie cloud expert apply -f bundle.yamlsucceeds for any bundle thatauggie cloud expert validateandapply --dry-runaccept — including the round-trip case ofapply-ing a freshexportwith no edits. Optional unset fields should be omitted from the request body, not sent asnull.Steps to reproduce
auggie cloud expert init --name diag-test -o /tmp/diag.yamlspec.expert.environment.idandspec.expert.model: claude-opus-4-7.auggie cloud expert validate -f /tmp/diag.yaml→ passes.auggie cloud expert apply --dry-run -f /tmp/diag.yaml→ passes.auggie cloud expert apply -f /tmp/diag.yaml→ 400,expected i32.Alternative reproduction (round-trip):
auggie cloud expert export <any-existing-expert-id> -o /tmp/x.yamlauggie cloud expert apply -f /tmp/x.yaml→ same 400.Workaround
A
NODE_OPTIONS=--require=<shim>that stripsnull-valued keys fromPOST /cloud-experts/experts/*bodies makes the apply succeed and the resulting expert is well-formed:With the shim,
applysucceeds and the expert is created correctly — confirming the server-side schema is fine and the CLI body is the only issue.Auggie version
999.999.999 (commit b7668abcf77)— this is the build shipping inside Augment Cloud agent VMs (/opt/augment/augment.mjs, symlinked from/usr/local/bin/auggie). I have not verified against the published@augmentcode/auggie0.24.0; the relevant code (Cdein the bundledaugment.mjs) is internal CLI logic so the bug is likely present there too, but worth a quick check.Request ID
1fc3ed43-a53b-4773-8841-b700e6b08b2e(Other request IDs from the same session that hit the same error:
377b94f9-d9c6-4a10-bfe8-ff21556a8590,fc74fea3-fd1b-4850-b066-bb45252fea82,960af909-4cc6-46d1-a0de-e96184402fec,e13887bb-2a81-4a79-a03c-2acc531639cd,7689da7a-15bd-48a2-9486-c7c28fd59bdd,a46dec8a-bb7d-484f-b185-0f3a353f9145— round-trip of Advisor export,b08024f3-72a5-4d59-bdf4-90f52d0512b7,4da66c18-fc1c-4ef0-a39c-3579e22bf740,11d5a401-57b6-48cf-9c45-3f3b9e44b102.)Environment details
Environment
sh/opt/augment/augment.mjs(symlinked from/usr/local/bin/auggie)999.999.999 (commit b7668abcf77)d15.api.augmentcode.comAnything else we need to know?
The bug is fully blocking
auggie cloud expert applyfor any tenant on this CLI build — every fresh expert and every round-trip update fails.expert validate/apply --dry-runare happy because the bug is in the request body, not the bundle, so static checks miss it.The minimal server-side-friendly fix is to spread the three optional
session_configkeys conditionally inCde, the same waycpu_cores,memory_mib,snapshot_id, etc. are already handled in the same function. The same probably applies to any otherundefined → nullenum field —vm_config.image_sourceandrouting_target.daemon_vm_idare already gated correctly;session_config.visibility/user_metadata/auto_cleanup_on_idleare not.