{"record":{"id":"5c0ff5e6dd3b6af5","repo":"antonmedv/fx","slug":"cannot-get-length-of-typeof-x","errorCode":null,"errorMessage":"Cannot get length of ${typeof x}","messagePattern":"Cannot get length of (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"internal/engine/stdlib.js","lineNumber":30,"sourceCode":"        parts.push(JSON.stringify(arg, null, 2))\n      }\n    }\n    println(parts.join(' '))\n  },\n}\n\nconst skip = Symbol('skip')\n\nfunction apply(fn, ...args) {\n  if (typeof fn === 'function') return fn(...args)\n  return fn\n}\n\nfunction len(x) {\n  if (Array.isArray(x)) return x.length\n  if (typeof x === 'string') return x.length\n  if (typeof x === 'object' && x !== null) return Object.keys(x).length\n  throw new Error(`Cannot get length of ${typeof x}`)\n}\n\nfunction uniq(x) {\n  if (Array.isArray(x)) return [...new Set(x)]\n  throw new Error(`Cannot get unique values of ${typeof x}`)\n}\n\nfunction sort(x) {\n  if (Array.isArray(x)) return x.sort()\n  throw new Error(`Cannot sort ${typeof x}`)\n}\n\nfunction isFalsely(x) {\n  return x === false || x === null || x === undefined\n}\n\nfunction filter(fn) {\n  return function (x) {","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/antonmedv/fx/blob/4f31cd3a0c5d66f1b4290a2719bab14a5cee8ebe/internal/engine/stdlib.js#L12-L48","documentation":"len(x) is the standard-library length helper: it returns the length of arrays and strings, and the number of own keys of plain objects. When x is any other type (number, boolean, null, undefined, function, symbol, bigint), no branch matches and it throws 'Cannot get length of <type>'. The library intentionally fails fast instead of returning 0 or NaN so callers notice they applied a collection function to a scalar.","triggerScenarios":"Calling len(42), len(true), len(null), len(undefined), or len(() => {}) — any value that is not an Array, string, or non-null object.","commonSituations":"Pipelines where an upstream step sometimes yields null instead of an empty array/string (e.g. missing JSON field parsed as null, an API returning no data), or applying len to a number that a config/split function returned instead of a string.","solutions":["Check the value's type before calling len and handle scalars explicitly (e.g. len(x ?? []))","Coerce or convert: String(x).length for strings, Object.keys(x ?? {}).length for possibly-null objects","If x may be null/undefined from a lookup, default it first: len(x || [])","Wrap the call in try/catch if the input type is genuinely dynamic and length is optional"],"exampleFix":"// before\nconst n = len(count)\n// after\nconst n = typeof count === 'number' ? count : len(count ?? [])","handlingStrategy":"type-guard","validationCode":"if (x == null || (typeof x !== 'string' && typeof x !== 'object')) throw new TypeError('len() requires an array, string, or object'); if (typeof x === 'object' && !Array.isArray(x) && Object.keys(x).length === 0) { /* empty object: len returns 0, fine */ }","typeGuard":"function hasLength(x) { return typeof x === 'string' || Array.isArray(x) || (x !== null && typeof x === 'object') }","tryCatchPattern":"let n; try { n = len(x) } catch (e) { if (e.message.startsWith('Cannot get length of')) { n = 0 } else { throw e } }","preventionTips":["Default nullable lookups before use: len(x ?? [])","Never assume a JSON field exists — null is an object but len(null) throws","Run data-shape validation at pipeline boundaries, not at point of use","Add Array.isArray/typeof asserts in dev builds"],"tags":["type-error","runtime","stdlib"],"backgroundTag":"invalid-argument-value","analyzedSha":"4f31cd3a0c5d66f1b4290a2719bab14a5cee8ebe","analyzedAt":"2026-09-02T02:17:47.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}