warpdotdev/warp · error · anyhow::Error

--vcpus is required when setting an instance shape for a run

Error message

--vcpus is required when setting an instance shape for a runner that has none

What it means

merge_instance_shape composes the (vcpus, memory_gb) pair for a runner update from new flags plus the runner's existing shape. If exactly one of --vcpus/--memory-gb is provided and the runner has no existing shape, the other dimension has no source, so the update is rejected instead of silently defaulting. This error fires when --vcpus is the missing dimension.

Source

Thrown at app/src/ai/agent_sdk/runner.rs:390

        (true, Some(name)) => name.to_string(),
        _ => existing_name.to_string(),
    }
}

/// Merge instance-shape overrides with the existing shape (`(vcpus, memory_gb)`),
/// allowing vCPUs and memory to be updated independently. Returns `None` when
/// there is no shape to set, or an error when only one dimension is provided for
/// a runner that has no existing shape to supply the other.
fn merge_instance_shape(
    new_vcpus: Option<i32>,
    new_memory_gb: Option<i32>,
    existing: Option<(i32, i32)>,
) -> Result<Option<(i32, i32)>> {
    if new_vcpus.is_none() && new_memory_gb.is_none() {
        return Ok(existing);
    }
    let vcpus = new_vcpus.or(existing.map(|(v, _)| v)).ok_or_else(|| {
        anyhow!("--vcpus is required when setting an instance shape for a runner that has none")
    })?;
    let memory_gb = new_memory_gb.or(existing.map(|(_, m)| m)).ok_or_else(|| {
        anyhow!("--memory-gb is required when setting an instance shape for a runner that has none")
    })?;
    Ok(Some((vcpus, memory_gb)))
}

fn os_to_gql(os: RunnerOsArg) -> RunnerOs {
    match os {
        RunnerOsArg::Linux => RunnerOs::Linux,
        RunnerOsArg::Macos => RunnerOs::Macos,
    }
}

/// Resolve a [`RunnerArchArg`] into a concrete [`RunnerArch`], mapping `auto`
/// to the default architecture for the given OS (x86-64 on Linux, aarch64 on
/// macOS).
fn resolve_arch(arch: RunnerArchArg, os: RunnerOsArg) -> RunnerArch {

View on GitHub (pinned to e72fd7aacb)

Solutions

  1. Pass both dimensions together: --vcpus N --memory-gb M
  2. If you truly want to change only one dimension, first establish a full shape, then later single-dimension updates inherit the other from it

Example fix

// before
oz runner update --uid rnr_x --memory-gb 8
# Error: --vcpus is required when setting an instance shape for a runner that has none

// after
oz runner update --uid rnr_x --vcpus 4 --memory-gb 8
Defensive patterns

Strategy: validation

Validate before calling

let existing: Option<(i32, i32)> = runner.instance_shape();
if existing.is_none() && (vcpus.is_some() ^ memory_gb.is_some()) {
    anyhow::bail!("shapeless runner: pass both --vcpus and --memory-gb");
}
merge_instance_shape(vcpus, memory_gb, existing)?;

Prevention

When it happens

Trigger: oz runner update --memory-gb 8 (vcpus flag absent) on a runner whose current config has no instance shape, so vcpus cannot be inherited from existing.

Common situations: Trying to scale one dimension of a freshly created shapeless runner; assuming the server fills in a default for the missing dimension; copying a partial update command from docs or a teammate.

Related errors


AI-assisted analysis of warpdotdev/warp@e72fd7aacb (2026-08-16). Data as JSON: /api/errors/9af73983ec660fbf. Report an issue: GitHub.