{"record":{"id":"d34c5a4c950a892a","repo":"emberjs/ember.js","slug":"createcache-must-be-passed-a-function-as-its-fir","errorCode":null,"errorMessage":"createCache() must be passed a function as its first parameter. Called with: ${String(fn)}","messagePattern":"createCache\\(\\) must be passed a function as its first parameter\\. Called with: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@glimmer/validator/lib/tracking.ts","lineNumber":146,"sourceCode":"}\n\nconst FN = Symbol('FN');\nconst LAST_VALUE = Symbol('LAST_VALUE');\nconst TAG = Symbol('TAG');\nconst SNAPSHOT = Symbol('SNAPSHOT');\nconst DEBUG_LABEL = Symbol('DEBUG_LABEL');\n\ninterface InternalCache<T = unknown> {\n  [FN]: (...args: unknown[]) => T;\n  [LAST_VALUE]: T | undefined;\n  [TAG]: Tag | undefined;\n  [SNAPSHOT]: Revision;\n  [DEBUG_LABEL]?: string | false | undefined;\n}\n\nexport function createCache<T>(fn: () => T, debuggingLabel?: string | false): Cache<T> {\n  if (DEBUG && !(typeof fn === 'function')) {\n    throw new Error(\n      `createCache() must be passed a function as its first parameter. Called with: ${String(fn)}`\n    );\n  }\n\n  let cache: InternalCache<T> = {\n    [FN]: fn,\n    [LAST_VALUE]: undefined,\n    [TAG]: undefined,\n    [SNAPSHOT]: -1,\n  };\n\n  if (DEBUG) {\n    cache[DEBUG_LABEL] = debuggingLabel;\n  }\n\n  return cache as unknown as Cache<T>;\n}\n","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/emberjs/ember.js/blob/26f97246a8bf2e28edf26ac3093da2e86c04ffc5/packages/@glimmer/validator/lib/tracking.ts#L128-L164","documentation":"createCache() memoizes the result of a function so it can be validated for staleness later. In DEBUG builds the validator library verifies the first argument is actually a function before wrapping it; passing anything else (undefined, null, a string, a misnamed import) throws immediately instead of failing mysteriously later.","triggerScenarios":"Calling createCache(x) where typeof x !== 'function' — e.g. an undefined callback due to a circular import, a forgotten arrow function (createCache(fn()) instead of createCache(fn)), or a null value from an optional dependency.","commonSituations":"Circular module imports resolving to undefined at call time; calling the function instead of passing it; typos in imports under tree-shaking/bundlers; Ember apps upgrading glimmer versions where a previously-optional argument became validated.","solutions":["Pass a function as the first argument: createCache(() => computeValue(), 'my label')","Log the argument with console.log(String(fn)) at the call site to see what was actually passed","Check for circular imports that leave the callback undefined at module-eval time","Fix accidental invocation: createCache(fn) not createCache(fn())"],"exampleFix":"// before\nconst cache = createCache(config.loader());\n// after\nconst cache = createCache(() => config.loader(), 'config-loader');","handlingStrategy":"validation","validationCode":"if (typeof fn !== 'function') { throw new TypeError('createCache requires a function, got: ' + String(fn)); }\nconst cache = createCache(fn, 'myCache');","typeGuard":"function isCallable(v) { return typeof v === 'function'; }","tryCatchPattern":null,"preventionTips":["Always pass a thunk (arrow function), never a call result","Beware circular imports: the callback module may be undefined at call time","Add a label argument so debug errors point at the right cache"],"tags":["debug","validation","glimmer"],"backgroundTag":"argument-type-mismatch","analyzedSha":"26f97246a8bf2e28edf26ac3093da2e86c04ffc5","analyzedAt":"2026-09-01T05:01:28.182Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}