Skip to content

API silently drops runtime_config.build_with and runtime_env #6210

Description

@danbarr

Bug description

The workload create API accepts a runtime_config object typed directly as templates.RuntimeConfig (pkg/api/v1/workload_types.go:49), and swagger documents all four of its fields (docs/server/swagger.yaml:4376-4419). But runtimeConfigFromRequest (pkg/api/v1/workload_service.go:506-527) only copies builder_image and additional_packages. build_with and runtime_env are dropped with no error.

The early return at workload_service.go:522 compounds it: a request setting only those two fields returns nil, so no runtime config reaches the build at all.

Steps to reproduce

curl -X POST http://localhost:8080/api/v1beta/workloads \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "arxiv-test",
    "image": "uvx://arxiv-mcp-server",
    "runtime_config": {
      "build_with": ["mcp<2"],
      "runtime_env": {"MY_FLAG": "1"}
    }
  }'

Compare against the equivalent CLI invocation, which honors both fields:

thv run --build-with 'mcp<2' uvx://arxiv-mcp-server

Expected behavior

Either the generated Dockerfile contains uv tool install --with 'mcp<2' and an ENV MY_FLAG="1" in the runtime stage, or the request is rejected with an error naming the unsupported fields.

Actual behavior

The request succeeds and both fields are silently ignored. The Dockerfile has no --with argument and no MY_FLAG. Because this request sets no other runtime_config field, runtimeConfigFromRequest returns nil and the build falls back entirely to transport defaults.

Additional context

The same two-field assumption repeats in runtimeConfigForImageBuild (merge at workload_service.go:569-578), getBaseRuntimeConfig (workload_service.go:583-597), and the response mapper (pkg/api/v1/workload_types.go:400-401), so a runtime config carrying those fields would not round-trip either.

Both fields work through the CLI path, which constructs templates.RuntimeConfig directly and lets loadRuntimeConfig merge and validate it (pkg/runner/protocol.go:172-233). Only the API path loses them. No test in pkg/api/v1/workload_service_test.go covers either field, which suggests an oversight rather than a deliberate API restriction.

Fix is either plumbing both fields through all four functions with validateRuntimeConfig extended to match, or rejecting them explicitly and removing them from the swagger schema. Silently ignoring documented fields is the worst of the three.

Environment

  • ToolHive version: v0.42.0 (2c623d57)

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions