Summary
When an agent is created from a GitHub source repo whose template.yaml declares a non-integer CPU value (e.g. Kubernetes-style cpu: \"0.5\"), agent creation aborts with an opaque ValueError: invalid literal for int() with base 10: '0.5'. The repo-access validation, MCP key creation, subscription assignment and env-var setup all succeed first, then the container-create step crashes on a raw int(cpu). The platform should validate/normalize template resource fields and return a clear, actionable error instead of crashing with a cryptic Python message — and should not leave partial side effects behind.
Component
Backend / Agent Service (container creation)
Priority
P2 — agent creation from an otherwise-valid source repo fails; workaround exists (edit the template to a valid CPU value), but the failure mode is opaque and leaves orphaned rows.
Error
ERROR services.agent_service.crud: Failed to create agent [AGENT]: invalid literal for int() with base 10: '0.5'
Location
- File:
src/backend/services/agent_service/crud.py
- Line: 741
- Function/Class: container-create block in the agent create path
- Same pattern (also unguarded):
src/backend/services/agent_service/lifecycle.py:554 — nano_cpus=int(cpu) * 1_000_000_000
src/backend/services/system_agent_service.py:248 — nano_cpus=int(resources.get(\"cpu\", \"4\")) * 1_000_000_000
Root Cause
The CPU value taken from the agent's template.yaml resources block is fed straight into int():
nano_cpus=int(config.resources.get('cpu') or _get_default_resource('cpu')) * 1_000_000_000,
A non-integer value such as cpu: "0.5" (or any Kubernetes-style spec) raises ValueError and aborts the entire create. There is no validation/normalization of template resource fields against the allowed set (cpu ∈ {1,2,4,8,16}, memory ∈ {1g,2g,4g,8g,16g,32g}) before they reach Docker.
The adjacent memory line has the same class of problem — it passes the raw value to Docker's mem_limit:
mem_limit=config.resources.get('memory') or _get_default_resource('memory'),
A Kubernetes-style memory: "512Mi" is not a valid Docker memory string (Docker expects 512m / 4g), so it would also fail; the int(cpu) error simply fires first.
Introduced by the #1126/#1128 change (apply CPU cgroup limit on Linux via nano_cpus), which added the unguarded int(cpu) at all three creation sites.
Reproduction Steps
- Create a GitHub repo whose
template.yaml contains a Kubernetes-style resources block:
resources:
cpu: "0.5"
memory: "512Mi"
- Create an agent pointed at that repo in source mode.
- Backend validates repo access, creates the MCP key, assigns a subscription, sets template env vars — then crashes at the
nano_cpus conversion.
- Observe: opaque
ValueError: invalid literal for int() with base 10: '0.5'. The agent_ownership row rolls back, but an orphaned mcp_api_keys row for the agent is left behind (one per attempt).
Suggested Fix
Validate and normalize resources.cpu and resources.memory against the allowed values before container creation, and raise a clear, actionable error on invalid input. Apply at all three creation sites (or factor into one shared helper):
VALID_CPU = {"1", "2", "4", "8", "16"}
def _normalize_cpu(value) -> str:
cpu = str(value or _get_default_resource("cpu"))
if cpu not in VALID_CPU:
raise ValueError(
f"Invalid cpu '{cpu}': must be one of {sorted(VALID_CPU, key=int)} (integer processors)"
)
return cpu
# at the call site:
nano_cpus=int(_normalize_cpu(config.resources.get('cpu'))) * 1_000_000_000,
Do the equivalent for memory (validate against {1g,2g,4g,8g,16g,32g}, or map common k8s suffixes → Docker form). Surfacing this as a 4xx validation error at the API boundary (rather than a 500 from deep in container creation) would be ideal.
Secondary: roll back the MCP key creation when create fails so a failed create leaves no orphan mcp_api_keys rows.
Environment
Related
Summary
When an agent is created from a GitHub source repo whose
template.yamldeclares a non-integer CPU value (e.g. Kubernetes-stylecpu: \"0.5\"), agent creation aborts with an opaqueValueError: invalid literal for int() with base 10: '0.5'. The repo-access validation, MCP key creation, subscription assignment and env-var setup all succeed first, then the container-create step crashes on a rawint(cpu). The platform should validate/normalize template resource fields and return a clear, actionable error instead of crashing with a cryptic Python message — and should not leave partial side effects behind.Component
Backend / Agent Service (container creation)
Priority
P2 — agent creation from an otherwise-valid source repo fails; workaround exists (edit the template to a valid CPU value), but the failure mode is opaque and leaves orphaned rows.
Error
Location
src/backend/services/agent_service/crud.pysrc/backend/services/agent_service/lifecycle.py:554—nano_cpus=int(cpu) * 1_000_000_000src/backend/services/system_agent_service.py:248—nano_cpus=int(resources.get(\"cpu\", \"4\")) * 1_000_000_000Root Cause
The CPU value taken from the agent's
template.yamlresourcesblock is fed straight intoint():A non-integer value such as
cpu: "0.5"(or any Kubernetes-style spec) raisesValueErrorand aborts the entire create. There is no validation/normalization of template resource fields against the allowed set (cpu ∈ {1,2,4,8,16},memory ∈ {1g,2g,4g,8g,16g,32g}) before they reach Docker.The adjacent memory line has the same class of problem — it passes the raw value to Docker's
mem_limit:A Kubernetes-style
memory: "512Mi"is not a valid Docker memory string (Docker expects512m/4g), so it would also fail; theint(cpu)error simply fires first.Introduced by the #1126/#1128 change (apply CPU cgroup limit on Linux via
nano_cpus), which added the unguardedint(cpu)at all three creation sites.Reproduction Steps
template.yamlcontains a Kubernetes-style resources block:nano_cpusconversion.ValueError: invalid literal for int() with base 10: '0.5'. Theagent_ownershiprow rolls back, but an orphanedmcp_api_keysrow for the agent is left behind (one per attempt).Suggested Fix
Validate and normalize
resources.cpuandresources.memoryagainst the allowed values before container creation, and raise a clear, actionable error on invalid input. Apply at all three creation sites (or factor into one shared helper):Do the equivalent for memory (validate against
{1g,2g,4g,8g,16g,32g}, or map common k8s suffixes → Docker form). Surfacing this as a 4xx validation error at the API boundary (rather than a 500 from deep in container creation) would be ideal.Secondary: roll back the MCP key creation when create fails so a failed create leaves no orphan
mcp_api_keysrows.Environment
0.6.0(commitcccac44d)Related
nano_cpus)src/backend/services/agent_service/crud.py,src/backend/services/agent_service/lifecycle.py,src/backend/services/system_agent_service.py