clockworklabs/SpacetimeDB · error · anyhow::Error

Permission denied for domains: {domains:?}

Error message

Permission denied for domains: {domains:?}

What it means

Multi-domain variant of the rename permission failure: the server returned `PermissionDeniedOnAny { domains }` — of the requested domain(s), at least one is not permitted for the authenticated identity. The CLI formats the whole offending list into the error. It comes from the same `PUT /v1/database/{identity}/names` endpoint used by `spacetime rename`.

Source

Thrown at crates/cli/src/subcommands/dns.rs:55

    let builder = reqwest::Client::new()
        .put(format!(
            "{}/v1/database/{database_identity}/names",
            config.get_host_url(server)?
        ))
        .header(reqwest::header::CONTENT_TYPE, "application/json")
        .body(serde_json::to_string(&[&domain])?);
    let builder = add_auth_header_opt(builder, &auth_header);

    let response = builder.send().await?;
    let status = &response.status();
    let result: SetDomainsResult = response.json_or_error().await?;

    if !status.is_success() {
        anyhow::bail!(match result {
            SetDomainsResult::Success => "".to_string(),
            SetDomainsResult::PermissionDenied { domain } => format!("Permission denied for domain: {domain}"),
            SetDomainsResult::PermissionDeniedOnAny { domains } =>
                format!("Permission denied for domains: {domains:?}"),
            SetDomainsResult::DatabaseNotFound => format!("Database {database_identity} not found"),
            SetDomainsResult::NotYourDatabase { .. } =>
                format!("You cannot rename {database_identity} because it is owned by another identity."),
            SetDomainsResult::OtherError(err) => err,
        });
    }

    println!("Name set to {domain} for identity {database_identity}.");

    Ok(())
}

View on GitHub (pinned to 524b4487d9)

Solutions

  1. Read the `domains` list in the message and drop or replace each denied name
  2. Retry with only domains you own, one at a time, to isolate the offender
  3. Verify the authenticated identity matches the domain owner (`spacetime identity show`)
Defensive patterns

Strategy: try-catch

Validate before calling

// If driving the HTTP API directly, validate ownership per domain first
for d in domains { if !owned(&client, &d)? { return Err(format!("not owned: {d}")); } }

Type guard

fn is_denied(msg: &str) -> bool { msg.starts_with("Permission denied for domains:") }

Try / catch

// Parse the domains list out of the error, retry the request with only the permitted subset, and report the excluded names to the operator.

Prevention

When it happens

Trigger: The request body carries a list of domains (the CLI sends one, but the endpoint/API accepts several) and any element is owned/reserved by another party; typically surfaces with multi-name tooling built on the same HTTP API rather than the bare CLI.

Common situations: Custom scripts calling the names endpoint with several candidate domains; partial ownership where you control some names but not others in the list.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16). Data as JSON: /api/errors/c4a42bfd23917e6d. Report an issue: GitHub.