nikivdev/code · error

jazz-tools did not return an app id

Error message

jazz-tools did not return an app id

What it means

create_jazz_app_credentials runs the jazz-tools CLI and derives the app id from the last non-empty line of its stdout. If the captured output has no non-empty lines, it throws 'jazz-tools did not return an app id', meaning the CLI produced no usable output (empty stdout).

Source

Thrown at src/storage.rs:368

    };

    if !output.status.success() {
        let stdout = String::from_utf8_lossy(&output.stdout);
        let stderr = String::from_utf8_lossy(&output.stderr);
        bail!(
            "jazz2 app create failed: {}{}",
            stdout.trim(),
            stderr.trim()
        );
    }

    let stdout = String::from_utf8_lossy(&output.stdout);
    let app_id = stdout
        .lines()
        .rev()
        .find(|line| !line.trim().is_empty())
        .map(|line| line.trim().to_string())
        .ok_or_else(|| anyhow::anyhow!("jazz-tools did not return an app id"))?;

    Ok(JazzAppCredentials {
        app_id,
        backend_secret: generate_secret("backend"),
        admin_secret: generate_secret("admin"),
    })
}

fn jazz_tools_package_spec() -> String {
    resolve_jazz_tools_package_spec(std::env::var(JAZZ_TOOLS_NPX_SPEC_ENV).ok().as_deref())
}

fn resolve_jazz_tools_package_spec(raw: Option<&str>) -> String {
    raw.map(str::trim)
        .filter(|value| !value.is_empty())
        .unwrap_or(DEFAULT_JAZZ_TOOLS_NPX_SPEC)
        .to_string()
}

View on GitHub (pinned to a747e741ae)

Solutions

  1. Run the jazz-tools command manually and confirm it prints an app id on stdout
  2. Check the command's stderr (captured by run_command_with_output) for the real failure and fix auth/install
  3. Verify the expected jazz-tools binary is first on PATH (which jazz-tools)
  4. Update code to also parse JSON output or exit status before trusting stdout

Example fix

// before
let app_id = stdout.lines().rev().find(|line| !line.trim().is_empty())...
// after
if !output.status.success() {
    anyhow::bail!("jazz-tools failed ({}): {}", output.status, stderr_trimmed);
}
let app_id = stdout.lines().rev().find(|line| !line.trim().is_empty())...
Defensive patterns

Strategy: validation

Validate before calling

let output = run_command_with_output(cmd)?;
if !output.status.success() {
    anyhow::bail!("jazz-tools exited with {}: {}", output.status, String::from_utf8_lossy(&output.stderr));
}
if String::from_utf8_lossy(&output.stdout).trim().is_empty() {
    anyhow::bail!("jazz-tools produced no stdout; is it installed and logged in?");
}

Try / catch

match create_jazz_app_credentials() {
    Ok(creds) => creds,
    Err(e) if e.to_string().contains("did not return an app id") => {
        eprintln!("run `jazz-tools` manually to see why it prints nothing");
        return Err(e);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Running create_jazz_app_credentials (via bootstrap_cloudflare_secrets or jazz_new) when the jazz-tools command exits without printing anything to stdout — e.g. command failed silently, wrong binary on PATH, or output went only to stderr.

Common situations: jazz-tools not installed or not logged in so it prints nothing; a wrapper script swallows output; a version of jazz-tools whose output format changed (e.g. JSON on stderr).

Related errors


AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/ccd4a49e363d1d12. Report an issue: GitHub.