{"record":{"id":"96e05e110670c1bb","repo":"neondatabase/neon","slug":"remote-storage-config-environment-variable-must","errorCode":null,"errorMessage":"'REMOTE_STORAGE_CONFIG' environment variable must be set to a valid remote storage TOML config","messagePattern":"'REMOTE_STORAGE_CONFIG' environment variable must be set to a valid remote storage TOML config","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pageserver/ctl/src/download_remote_object.rs","lineNumber":44,"sourceCode":"    /// Examples:\n    ///   \"wal/3aa8f.../00000001000000000000000A\"\n    ///   \"pageserver/v1/tenants/<tenant_id>/timelines/<timeline_id>/layer_12345\"\n    pub remote_path: String,\n\n    /// Path of the local file to create. Existing file will be overwritten.\n    ///\n    /// Examples:\n    ///   \"./segment\"\n    ///   \"/tmp/layer_12345.parquet\"\n    pub output_file: Utf8PathBuf,\n}\n\npub(crate) async fn main(cmd: &DownloadRemoteObjectCmd) -> anyhow::Result<()> {\n    use remote_storage::{DownloadOpts, GenericRemoteStorage, RemotePath, RemoteStorageConfig};\n\n    // Fetch remote storage configuration from the environment\n    let config_str = std::env::var(\"REMOTE_STORAGE_CONFIG\").map_err(|_| {\n        anyhow::anyhow!(\n            \"'REMOTE_STORAGE_CONFIG' environment variable must be set to a valid remote storage TOML config\"\n        )\n    })?;\n\n    let config = RemoteStorageConfig::from_toml_str(&config_str)?;\n\n    // Initialise remote storage client\n    let storage = GenericRemoteStorage::from_config(&config).await?;\n\n    // RemotePath must be relative – leading slashes confuse the parser.\n    let remote_path_str = cmd.remote_path.trim_start_matches('/');\n    let remote_path = RemotePath::from_string(remote_path_str)?;\n\n    let cancel = CancellationToken::new();\n\n    println!(\n        \"Downloading '{remote_path}' from remote storage bucket {:?} ...\",\n        config.storage.bucket_name()","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/neondatabase/neon/blob/8f60b04da47ffefe0e52bda2440134b42874eb75/pageserver/ctl/src/download_remote_object.rs#L26-L62","documentation":"The pageserver_ctl download-remote-object command builds its remote storage client exclusively from the REMOTE_STORAGE_CONFIG environment variable, which must hold the remote storage TOML (the same block the pageserver uses for its remote_storage configuration). If the variable is unset or not valid Unicode, the command fails immediately with this error.","triggerScenarios":"Running pageserver_ctl download-remote-object in a shell, cron job, or container where REMOTE_STORAGE_CONFIG was never exported.","commonSituations":"Expecting a --config flag instead of an env var; running the ctl from a different shell than the one that holds the pageserver config; CI or systemd units that do not forward the environment.","solutions":["Export the variable with the remote storage TOML inline: REMOTE_STORAGE_CONFIG=\"$(cat remote_storage.toml)\" pageserver_ctl download-remote-object ...","Copy the remote_storage block from the pageserver's configuration; it must be valid TOML because RemoteStorageConfig::from_toml_str parses it next.","For S3-like targets include the same bucket_name, region, and prefix_in_bucket values the pageserver uses, or the later download will address the wrong bucket."],"exampleFix":"# before\npageserver_ctl download-remote-object --remote-path tenant-id/timeline-id/layer-file\n# -> \"'REMOTE_STORAGE_CONFIG' environment variable must be set ...\"\n\n# after\nexport REMOTE_STORAGE_CONFIG=\"$(cat /etc/neon/remote_storage.toml)\"\npageserver_ctl download-remote-object --remote-path tenant-id/timeline-id/layer-file --output-file ./layer-file","handlingStrategy":"validation","validationCode":"#!/usr/bin/env bash\n# fail fast with a clear message before invoking the ctl\nif [ -z \"${REMOTE_STORAGE_CONFIG:-}\" ]; then\n  echo \"REMOTE_STORAGE_CONFIG is empty; export the remote storage TOML first\" >&2\n  exit 1\nfi\npageserver_ctl download-remote-object \"$@\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Export REMOTE_STORAGE_CONFIG in the shell profile or wrapper script used for ctl operations.","Keep the remote storage TOML in one file and load it with REMOTE_STORAGE_CONFIG=\"$(cat file.toml)\".","Document in runbooks that this subcommand reads config from the environment, not a flag."],"tags":["rust","neon","ctl","environment-variable","remote-storage"],"backgroundTag":"missing-env-var","analyzedSha":"8f60b04da47ffefe0e52bda2440134b42874eb75","analyzedAt":"2026-08-16T23:39:28.135Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}