neondatabase/neon · error
setting scheduling policy unsuccessful for safekeeper
Error message
setting scheduling policy unsuccessful for safekeeper {node_id}: {} What it means
storcon_cli / the control plane asks the storage controller to change a safekeeper's scheduling policy via POST control/v1/safekeeper/{node_id}. Any non-2xx HTTP response is reported with the node id and status code; the response body is not included in the message.
Solutions
- List registered safekeepers via the storcon CLI and confirm the node id exists
- Check the storage controller's logs for the server-side reason behind the status code
- Authenticate the CLI if storcon requires JWT
- Validate the scheduling policy value before sending
Defensive patterns
Strategy: try-catch
Validate before calling
let registered: Vec<NodeId> = storcon.list_safekeepers().await?;
anyhow::ensure!(registered.contains(&node_id), "node {node_id} not registered in storcon"); Try / catch
let resp = dispatch(Method::POST, format!("control/v1/safekeeper/{node_id}"), Some(req)).await?;
match resp.status() {
s if s.is_success() => {}
StatusCode::NOT_FOUND => { /* node unknown: list safekeepers, re-register */ }
StatusCode::UNAUTHORIZED => { /* obtain/refresh the JWT */ }
s => { /* read the response body for details; check storcon logs */ }
} Prevention
- Verify node ids with a list call before mutating them
- Log the response body, not just the status code
- Keep the CLI and the storage controller on the same version
When it happens
Trigger: The node id is not registered in storcon's database (404), the policy payload is invalid (400), auth is required but the client is unauthenticated (401), or storcon hit an internal error (500) applying the policy.
Common situations: Passing a safekeeper node id that was never registered, a stale storcon database after re-adding safekeepers, auth enabled on storcon while the CLI lacks a token.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- Failed to capture events
- Failed to check node status
- Safekeeper set up for auth but no private key specified
- cannot parse query param
- createdb failed with status
AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16).
Data as JSON: /api/errors/83c290af70ed7563.
Report an issue: GitHub.
Appendix: source
Thrown at control_plane/src/storage_controller.rs:927
Ok(response.generation)
}
#[instrument(skip(self))]
pub async fn upsert_safekeeper(
&self,
node_id: NodeId,
request: serde_json::Value,
) -> anyhow::Result<()> {
let resp = self
.dispatch_inner::<serde_json::Value>(
Method::POST,
format!("control/v1/safekeeper/{node_id}"),
Some(request),
)
.await?;
if !resp.status().is_success() {
anyhow::bail!(
"setting scheduling policy unsuccessful for safekeeper {node_id}: {}",
resp.status()
);
}
Ok(())
}
#[instrument(skip(self))]
pub async fn safekeeper_scheduling_policy(
&self,
node_id: NodeId,
scheduling_policy: SkSchedulingPolicy,
) -> anyhow::Result<()> {
self.dispatch::<SafekeeperSchedulingPolicyRequest, ()>(
Method::POST,
format!("control/v1/safekeeper/{node_id}/scheduling_policy"),
Some(SafekeeperSchedulingPolicyRequest { scheduling_policy }),
)View on GitHub (pinned to 8f60b04da4)