{"id":"e59c1aa1f589eafd","repo":"redis/redis","slug":"err-invalid-arguments-you-need-to-pass-either-a","errorCode":null,"errorMessage":"[ERR] Invalid arguments: you need to pass either a valid address (ie. 120.0.0.1:7000) or space separated IP and port (ie. 120.0.0.1 7000)\n","messagePattern":"\\[ERR\\] Invalid arguments: you need to pass either a valid address \\(ie\\. 120\\.0\\.0\\.1:7000\\) or space separated IP and port \\(ie\\. 120\\.0\\.0\\.1 7000\\)\n","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/redis-cli.c","lineNumber":7769,"sourceCode":"        sleep(1);\n        clusterManagerWaitForClusterJoin();\n        clusterManagerLogInfo(\">>> Configure node as replica of %s:%d.\\n\",\n                              master_node->ip, master_node->port);\n        freeReplyObject(reply);\n        reply = CLUSTER_MANAGER_COMMAND(new_node, \"CLUSTER REPLICATE %s\",\n                                        master_node->name);\n        if (!(success = clusterManagerCheckRedisReply(new_node, reply, NULL)))\n            goto cleanup;\n    }\n    clusterManagerLogOk(\"[OK] New node added correctly.\\n\");\ncleanup:\n    if (!added && new_node) freeClusterManagerNode(new_node);\n    if (reply) freeReplyObject(reply);\n    if (function_restore_reply) freeReplyObject(function_restore_reply);\n    if (function_list_reply) freeReplyObject(function_list_reply);\n    return success;\ninvalid_args:\n    fprintf(stderr, CLUSTER_MANAGER_INVALID_HOST_ARG);\n    return 0;\n}\n\nstatic int clusterManagerCommandDeleteNode(int argc, char **argv) {\n    UNUSED(argc);\n    int success = 1;\n    int port = 0;\n    char *ip = NULL;\n    if (!getClusterHostFromCmdArgs(1, argv, &ip, &port)) goto invalid_args;\n    char *node_id = argv[1];\n    clusterManagerLogInfo(\">>> Removing node %s from cluster %s:%d\\n\",\n                          node_id, ip, port);\n    clusterManagerNode *ref_node = clusterManagerNewNode(ip, port, 0);\n    clusterManagerNode *node = NULL;\n\n    // Load cluster information\n    if (!clusterManagerLoadInfoFromNode(ref_node)) return 0;\n","sourceCodeStart":7751,"sourceCodeEnd":7787,"githubUrl":"https://github.com/redis/redis/blob/3acc0c49cf5ad2af9425d333e62728342dd6159b/src/redis-cli.c#L7751-L7787","documentation":"Printed via the CLUSTER_MANAGER_INVALID_HOST_ARG macro (src/redis-cli.c:7769) from clusterManagerCommandAddNode's `invalid_args` label when getClusterHostFromCmdArgs fails for either the new-node argument (argv[0]) or the reference-cluster argument (argv[1..]). The command needs exactly two host specs and could not extract an ip:port from one of them.","triggerScenarios":"Invoke `--cluster add-node` with the wrong shape: only one argument, missing `:port`, an empty port token, or non-numeric port so atoi yields 0 (getClusterHostFromCmdArgs rejects !port). Both the new node and the existing cluster reference must parse.","commonSituations":"Forgetting the second (reference cluster) argument; passing `add-node host1 host2` instead of `host1:port host2:port`; copy-paste leaving the port off one side; shell variable that expanded to an empty string for the port token.","solutions":["Provide both targets in `ip:port` form: `redis-cli --cluster add-node <newip>:<newport> <existingip>:<existingport>`.","Verify argument count is exactly two host specs (flags like --cluster-slave aside).","Ensure ports are non-zero numeric; avoid bare hostnames without a `:port`.","Echo the command first to catch empty `$NEWPORT` / `$REFPORT` shell expansions."],"exampleFix":"// before\nredis-cli --cluster add-node 10.0.0.9 10.0.0.1\n// after\nredis-cli --cluster add-node 10.0.0.9:7000 10.0.0.1:7000","handlingStrategy":"validation","validationCode":"// Validate the CLUSTER-related CLI argv (address OR space-separated ip+port) before dispatch.\nfunction validateClusterArgs(argv) {\n  const args = Array.isArray(argv) ? argv : String(argv).trim().split(/\\s+/);\n  if (args.length === 1) {\n    return validateAddressFormat(args[0]); // reuse [123] validator\n  }\n  if (args.length === 2) {\n    const [host, portStr] = args;\n    if (!host || !/^(\\[[^\\]]+\\]|[A-Za-z0-9.:-]+)$/.test(host)) {\n      throw new Error('Invalid arguments: pass host:port OR host port');\n    }\n    const port = Number(portStr);\n    if (!Number.isInteger(port) || port < 1 || port > 65535) {\n      throw new Error('Invalid arguments: port out of range');\n    }\n    return { host: host.replace(/^\\[|\\]$/g, ''), port };\n  }\n  throw new Error('Invalid arguments: pass a valid address (host:port) or space-separated host port');\n}","typeGuard":"function isClusterArgvShape(v) {\n  if (!Array.isArray(v)) return false;\n  if (v.length < 1 || v.length > 2) return false;\n  return v.every(x => typeof x === 'string' && x.trim().length > 0);\n}","tryCatchPattern":"try {\n  target = validateClusterArgs(process.argv.slice(idx));\n} catch (e) {\n  if (/Invalid arguments/i.test(String(e.message))) {\n    console.error('Usage: <host:port | host port>');\n    process.exit(2);\n  }\n  throw e;\n}","preventionTips":["Accept exactly two shapes — 'host:port' or 'host port' — and reject everything else explicitly","Coalesce both forms into a typed {host, port} object at the boundary so downstream code is uniform","Print a usage hint on validation failure so the user sees the expected shape","Treat 'too many args' and 'too few args' as distinct, explicit errors","Reuse the same address parser across all three argv sites [127], [128], [129]"],"tags":["cluster-manager","add-node","arguments","cli-usage","parsing"],"analyzedSha":"3acc0c49cf5ad2af9425d333e62728342dd6159b","analyzedAt":"2026-08-01T22:07:56.715Z","schemaVersion":2}