{"record":{"id":"a6eb31262da3b66b","repo":"denoland/deno","slug":"err-invalid-cursor-pos","errorCode":"ERR_INVALID_CURSOR_POS","errorMessage":"Cannot set cursor row without setting its column","messagePattern":"Cannot set cursor row without setting its column","errorType":"validation","errorClass":"ERR_INVALID_CURSOR_POS","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/internal/readline/callbacks.mjs","lineNumber":72,"sourceCode":"function cursorTo(stream, x, y, callback) {\n  if (callback !== undefined) {\n    validateFunction(callback, \"callback\");\n  }\n\n  if (typeof y === \"function\") {\n    callback = y;\n    y = undefined;\n  }\n\n  if (NumberIsNaN(x)) throw new ERR_INVALID_ARG_VALUE(\"x\", x);\n  if (NumberIsNaN(y)) throw new ERR_INVALID_ARG_VALUE(\"y\", y);\n\n  if (stream == null || (typeof x !== \"number\" && typeof y !== \"number\")) {\n    if (typeof callback === \"function\") process.nextTick(callback, null);\n    return true;\n  }\n\n  if (typeof x !== \"number\") throw new ERR_INVALID_CURSOR_POS();\n\n  const data = typeof y !== \"number\" ? CSI`${x + 1}G` : CSI`${y + 1};${x + 1}H`;\n  return stream.write(data, callback);\n}\n\n/**\n * moves the cursor relative to its current location\n */\n\nfunction moveCursor(stream, dx, dy, callback) {\n  if (callback !== undefined) {\n    validateFunction(callback, \"callback\");\n  }\n\n  if (stream == null || !(dx || dy)) {\n    if (typeof callback === \"function\") process.nextTick(callback, null);\n    return true;\n  }","sourceCodeStart":54,"sourceCodeEnd":90,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/internal/readline/callbacks.mjs#L54-L90","documentation":"After the NaN checks, cursorTo takes a silent no-op path when the stream is null or BOTH coordinates are non-numbers. It throws ERR_INVALID_CURSOR_POS ('Cannot set cursor row without setting its column') only when y is a number but x is not: you cannot address a row without a column because the emitted ANSI sequence needs both (y+1;x+1 H).","triggerScenarios":"readline.cursorTo(process.stdout, undefined, 5); cursorTo(stream, null, 3); x defaulted to undefined by an options-destructuring bug while y was supplied.","commonSituations":"Wrapper functions like moveTo(stream, opts) that forward opts.x/opts.y when only y was provided; optional-parameter code where the middle argument is skipped: cursorTo(stream, undefined, row).","solutions":["Always supply the column when you supply the row: cursorTo(stream, 0, row)","In wrappers, normalize: const X = Number.isFinite(x) ? x : 0 before forwarding","If only a row move is truly needed, emit the relative move with readline.moveCursor(stream, 0, dy) instead"],"exampleFix":"// before\nreadline.cursorTo(stream, undefined, targetRow);\n\n// after\nreadline.cursorTo(stream, 0, targetRow);","handlingStrategy":"validation","validationCode":"function cursorToSafe(stream: NodeJS.WriteStream, x?: number, y?: number) {\n  const hasX = Number.isFinite(x);\n  const hasY = Number.isFinite(y);\n  if (hasX && hasY) readline.cursorTo(stream, x, y);\n  else if (hasX) readline.cursorTo(stream, x);\n  // never send y without x\n}","typeGuard":null,"tryCatchPattern":"try {\n  readline.cursorTo(stream, x, y);\n} catch (err) {\n  if (err?.code === 'ERR_INVALID_CURSOR_POS') {\n    readline.cursorTo(stream, 0, y);\n  } else throw err;\n}","preventionTips":["Never skip the middle argument: use 0 for the column when only the row matters","For relative row moves prefer readline.moveCursor(stream, 0, dy)"],"tags":["readline","tty","node-compat","deno","cursor"],"backgroundTag":"readline-cursor-position","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-26T04:18:47.238Z"}