{"record":{"id":"b8353e6e0e4e1745","repo":"neondatabase/neon","slug":"must-specify-exactly-one-target","errorCode":null,"errorMessage":"must specify exactly one target","messagePattern":"must specify exactly one target","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pageserver/pagebench/src/cmd/aux_files.rs","lineNumber":50,"sourceCode":"\nasync fn main_impl(args: Args) -> anyhow::Result<()> {\n    let args: &'static Args = Box::leak(Box::new(args));\n\n    let mgmt_api_client = Arc::new(pageserver_client::mgmt_api::Client::new(\n        reqwest::Client::new(), // TODO: support ssl_ca_file for https APIs in pagebench.\n        args.mgmt_api_endpoint.clone(),\n        args.pageserver_jwt.as_deref(),\n    ));\n\n    // discover targets\n    let timelines: Vec<TenantTimelineId> = crate::util::cli::targets::discover(\n        &mgmt_api_client,\n        crate::util::cli::targets::Spec {\n            limit_to_first_n_targets: None,\n            targets: {\n                if let Some(targets) = &args.targets {\n                    if targets.len() != 1 {\n                        anyhow::bail!(\"must specify exactly one target\");\n                    }\n                    Some(targets.clone())\n                } else {\n                    None\n                }\n            },\n        },\n    )\n    .await?;\n\n    let timeline = timelines[0];\n    let tenant_shard_id = TenantShardId::unsharded(timeline.tenant_id);\n    let timeline_id = timeline.timeline_id;\n\n    println!(\"operating on timeline {timeline}\");\n\n    mgmt_api_client\n        .set_tenant_config(&TenantConfigRequest {","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/neondatabase/neon/blob/8f60b04da47ffefe0e52bda2440134b42874eb75/pageserver/pagebench/src/cmd/aux_files.rs#L32-L68","documentation":"The pagebench aux-files subcommand benchmarks exactly one timeline. If --targets is supplied, it must contain exactly one tenant/timeline entry; zero or multiple entries are rejected before target discovery runs. Omitting --targets entirely is allowed: the tool auto-discovers timelines and uses the first one.","triggerScenarios":"Running pagebench aux-files with a --targets list holding two or more entries, or an empty list; other pagebench subcommands accept multiple targets, so reused invocations fail here.","commonSituations":"Copy-pasting a multi-target list from a different pagebench subcommand; scripts that always pass --targets even when the list is empty.","solutions":["Pass exactly one target entry with --targets, for example the single tenant/timeline pair to benchmark.","Or omit --targets entirely to let the tool auto-discover and pick the first timeline."],"exampleFix":"# before\npagebench aux-files --mgmt-api-endpoint http://127.0.0.1:9898 --targets tenant1:tl1,tenant2:tl2\n# -> \"must specify exactly one target\"\n\n# after\npagebench aux-files --mgmt-api-endpoint http://127.0.0.1:9898 --targets tenant1:tl1","handlingStrategy":"validation","validationCode":"#!/usr/bin/env bash\n# aux-files benchmarks exactly one timeline\nif [ -n \"${TARGETS:-}\" ]; then\n  count=$(echo \"$TARGETS\" | awk -F, '{print NF}')\n  [ \"$count\" -eq 1 ] || { echo \"aux-files needs exactly one target, got $count\" >&2; exit 1; }\nfi\npagebench aux-files --mgmt-api-endpoint \"$ENDPOINT\" ${TARGETS:+--targets \"$TARGETS\"} \"$@\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remember aux-files is single-target, unlike other pagebench subcommands that fan out.","Omit --targets to auto-discover instead of passing an empty list."],"tags":["rust","neon","pagebench","cli","input-validation"],"backgroundTag":"invalid-cli-argument-value","analyzedSha":"8f60b04da47ffefe0e52bda2440134b42874eb75","analyzedAt":"2026-08-16T23:39:28.135Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}