{"record":{"id":"02ab090158df1615","repo":"emberjs/ember.js","slug":"fnname-can-only-be-used-on-an-instance-of-a-c","errorCode":null,"errorMessage":"${fnName}() can only be used on an instance of a cache created with createCache(). Called with: ${String(value)}","messagePattern":"(.+?)\\(\\) can only be used on an instance of a cache created with createCache\\(\\)\\. Called with: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@glimmer/validator/lib/tracking.ts","lineNumber":205,"sourceCode":"  return cache[LAST_VALUE];\n}\n\nexport function isConst(cache: Cache): boolean {\n  assertCache(cache, 'isConst');\n\n  let tag = cache[TAG];\n\n  assertTag(tag, cache);\n\n  return isConstTag(tag);\n}\n\nfunction assertCache<T>(\n  value: Cache<T> | InternalCache<T>,\n  fnName: string\n): asserts value is InternalCache<T> {\n  if (DEBUG && !(typeof value === 'object' && FN in value)) {\n    throw new Error(\n      `${fnName}() can only be used on an instance of a cache created with createCache(). Called with: ${String(\n        // eslint-disable-next-line @typescript-eslint/no-base-to-string -- @fixme\n        value\n      )}`\n    );\n  }\n}\n\n// replace this with `expect` when we can\nfunction assertTag(tag: Tag | undefined, cache: InternalCache): asserts tag is Tag {\n  if (DEBUG && tag === undefined) {\n    throw new Error(\n      `isConst() can only be used on a cache once getValue() has been called at least once. Called with cache function:\\n\\n${String(\n        cache[FN]\n      )}`\n    );\n  }\n}","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/emberjs/ember.js/blob/26f97246a8bf2e28edf26ac3093da2e86c04ffc5/packages/@glimmer/validator/lib/tracking.ts#L187-L223","documentation":"getValue() and isConst() only operate on caches produced by createCache(). In DEBUG builds assertCache checks the value is an object carrying the internal FN marker symbol; anything else throws. This catches passing a raw function, plain object, or a value created by another memoization utility.","triggerScenarios":"Calling getValue(x) or isConst(x) where x is not the return value of createCache() — e.g. passing the original function itself, a result of the cached function, or an object from a different memoization lib.","commonSituations":"Mixing up the cache object with the cached value; two copies of @glimmer/validator in the bundle so the FN symbol differs (duplicate dependency after dependency resolution changes); refactoring away createCache but leaving getValue calls.","solutions":["Pass exactly the object returned by createCache(), not the wrapped function or its result","Verify only one copy of @glimmer/validator is installed (npm ls @glimmer/validator; dedupe)","Search for getValue(/isConst( calls and confirm each argument comes from createCache","Re-run against a debug build to get this check rather than silent undefined behavior in production"],"exampleFix":"// before\nconst value = getValue(myCompute);\n// after\nconst cache = createCache(myCompute, 'myCompute');\nconst value = getValue(cache);","handlingStrategy":"validation","validationCode":"function isCache(v) { return v !== null && typeof v === 'object' && typeof v.getValue === 'function' || (v && v.constructor && String(v).includes('cache')); }\nif (!isCache(maybeCache)) throw new TypeError('getValue requires a createCache() result');","typeGuard":"function isCache(v) { return typeof v === 'object' && v !== null; } // exact marker symbol is internal; track creation yourself: const caches = new WeakSet(); then isCache = v => caches.has(v)","tryCatchPattern":"try { value = getValue(cache); } catch (e) { if (String(e).includes('createCache()')) { cache = createCache(fn); value = getValue(cache); } else { throw e; } }","preventionTips":["Keep the cache object, never confuse it with the cached value","Dedupe @glimmer/validator so the FN symbol is shared","Centralize cache creation in a helper that also registers it"],"tags":["debug","validation","glimmer"],"backgroundTag":"invalid-cache-instance","analyzedSha":"26f97246a8bf2e28edf26ac3093da2e86c04ffc5","analyzedAt":"2026-09-01T05:01:28.182Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}