neondatabase/neon · error

setting scheduling policy unsuccessful for safekeeper {node_

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.

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)

Solutions

  1. List registered safekeepers via the storcon CLI and confirm the node id exists
  2. Check the storage controller's logs for the server-side reason behind the status code
  3. Authenticate the CLI if storcon requires JWT
  4. 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

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.

Related errors


AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16). Data as JSON: /api/errors/83c290af70ed7563. Report an issue: GitHub.