{"record":{"id":"66df92f6a62e88b0","repo":"rqlite/rqlite","slug":"errnodeidrequired","errorCode":"ErrNodeIDRequired","errorMessage":"node required","messagePattern":"node required","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cluster/join.go","lineNumber":16,"sourceCode":"package cluster\n\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"log\"\n\t\"os\"\n\t\"time\"\n\n\t\"github.com/rqlite/rqlite/v10/cluster/proto\"\n\tcommand \"github.com/rqlite/rqlite/v10/command/proto\"\n)\n\nvar (\n\t// ErrNodeIDRequired is returned a join request doesn't supply a node ID\n\tErrNodeIDRequired = errors.New(\"node required\")\n\n\t// ErrJoinFailed is returned when a node fails to join a cluster\n\tErrJoinFailed = errors.New(\"failed to join cluster\")\n\n\t// ErrJoinCanceled is returned when a join operation is canceled\n\tErrJoinCanceled = errors.New(\"join operation canceled\")\n\n\t// ErrNotifyFailed is returned when a node fails to notify another node\n\tErrNotifyFailed = errors.New(\"failed to notify node\")\n)\n\n// Joiner executes a node-join operation.\ntype Joiner struct {\n\tnumAttempts     int\n\tattemptInterval time.Duration\n\n\tclient *Client\n\tcreds  *proto.Credentials","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/rqlite/rqlite/blob/7586a4d1bdbd9a5a80021664c5a863cd850adb60/cluster/join.go#L1-L34","documentation":"ErrNodeIDRequired (cluster/join.go:16) is returned by Joiner.Do when the id parameter is an empty string. A join request must identify the joining node, so Joiner refuses to send a join with a blank node ID.","triggerScenarios":"Calling Joiner.Do(ctx, targetAddrs, \"\", addr, suffrage) — i.e. passing an empty id — which happens upstream when rqlited is started without -node-id while joining a cluster that requires node IDs.","commonSituations":"Running rqlited with -join but forgetting -node-id in newer versions where node IDs are mandatory for joins; scripting the join API and omitting the id field.","solutions":["Start the node with an explicit -node-id flag.","If calling Joiner.Do programmatically, pass a non-empty unique id.","Check for empty environment-variable-derived node ID before launch."],"exampleFix":"// before\nrqlited -join leader.example.com:4001 data\n// ErrNodeIDRequired: node required\n\n// after\nrqlited -node-id node1 -join leader.example.com:4001 data","handlingStrategy":"validation","validationCode":"if id == \"\" {\n    return \"\", errors.New(\"node ID must be non-empty before calling Joiner.Do\")\n}","typeGuard":null,"tryCatchPattern":"if _, err := joiner.Do(ctx, addrs, id, addr, suffrage); errors.Is(err, cluster.ErrNodeIDRequired) {\n    log.Fatal(\"start node with an explicit -node-id\")\n}","preventionTips":["Always pass -node-id when using -join","Fail fast at config parsing if node ID is empty","Avoid deriving node ID from potentially empty env vars without a default"],"tags":["cluster","join","validation","node-id"],"backgroundTag":"missing-required-argument","analyzedSha":"7586a4d1bdbd9a5a80021664c5a863cd850adb60","analyzedAt":"2026-09-03T07:03:02.260Z","contentChangedAt":"2026-09-03T07:03:02.260Z","schemaVersion":2},"datasetVersion":"2026-09-10T12:17:11.382Z"}