rqlite/rqlite · warning
remote remove node not authorized
Error message
remote remove node not authorized
What it means
In http.Service.handleRemove, when the leader-forwarded remove-node call returns proxy.ErrUnauthorized, the handler responds HTTP 401 with the literal body 'remote remove node not authorized'. This means the remote leader rejected the node-remove request because the client's basic-auth credentials are missing or lack permission for the operation. It is an authentication/authorization failure, not a transport or cluster-state problem.
Source
Thrown at http/service.go:577
}
rn := &proto.RemoveNodeRequest{
Id: remoteID,
}
addr, err := s.proxy.Remove(r.Context(), rn, makeCredentials(r), qp.Timeout(defaultTimeout), qp.Redirect())
if err != nil {
if errors.Is(err, proxy.ErrNotLeader) {
s.DoRedirect(w, r, qp)
return
}
if errors.Is(err, proxy.ErrLeaderNotFound) {
stats.Add(numLeaderNotFound, 1)
http.Error(w, proxy.ErrLeaderNotFound.Error(), http.StatusServiceUnavailable)
return
}
if errors.Is(err, proxy.ErrUnauthorized) {
http.Error(w, "remote remove node not authorized", http.StatusUnauthorized)
return
}
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set(ServedByHTTPHeader, addr)
}
// handleSQLAnalyze handles requests to analyze and show SQL rewriting.
func (s *Service) handleSQLAnalyze(w http.ResponseWriter, r *http.Request, qp QueryParams) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
if !s.CheckRequestPerm(r, auth.PermQuery) {
w.WriteHeader(http.StatusUnauthorized)
return
}
if r.Method != "GET" && r.Method != "POST" {View on GitHub (pinned to 7586a4d1bd)
Solutions
- Send valid basic-auth credentials of a user with sufficient permissions: curl -XDELETE -u 'user:pass' ...
- Check the node's auth configuration / create or elevate a user permitted to remove nodes.
- Verify no intermediate proxy strips the Authorization header.
- Re-test; if 401 persists, confirm the credentials against the auth config on the leader node.
Example fix
// before curl -XDELETE 'localhost:4001/db/node?addr=1.2.3.4:4002' # 401 remote remove node not authorized // after curl -XDELETE -u 'admin:secret' 'localhost:4001/db/node?addr=1.2.3.4:4002'
Defensive patterns
Strategy: validation
Validate before calling
function assertRemoveAuth(creds) {
if (!creds || !creds.username || !creds.password) {
throw new Error('rqlite auth enabled: basic-auth credentials required for node removal')
}
} Try / catch
const res = await fetch(url, {method:'DELETE', headers:{Authorization: basicAuth(user, pass)}})
if (res.status === 401 && (await res.text()).includes('not authorized')) {
// refresh credentials / verify user permission level, then retry
throw new Error('node removal rejected: invalid or insufficient credentials')
} Prevention
- Store rqlite credentials in a secret manager and inject into automation configs.
- Provision an admin-level user specifically for cluster administration tasks.
- Check that reverse proxies pass the Authorization header through unchanged.
- Rotate credentials consistently across all nodes and clients; test after auth changes.
When it happens
Trigger: DELETE /db/node on an auth-enabled cluster without credentials, with wrong username/password, or with a user lacking sufficient permission level for node removal (join/remove operations require elevated auth).
Common situations: Cluster deployed with -auth but automation scripts not updated to send credentials; auth config changed (users recreated) leaving old credentials invalid; reverse proxy stripping the Authorization header; users created with too-low permission level.
Related errors
- unauthorized
- unauthorized
- remote query not authorized
- remote Request not authorized
- text || ("HTTP " + resp.status)
AI-assisted analysis of rqlite/rqlite@7586a4d1bd (2026-09-03).
Data as JSON: /api/errors/613fc72b95808a1a.
Report an issue: GitHub.