{"record":{"id":"6dc914949ff7521b","repo":"hcengineering/platform","slug":"invalid-key","errorCode":null,"errorMessage":"Invalid key","messagePattern":"Invalid key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pods/preview/src/cache.ts","lineNumber":140,"sourceCode":"            this.ctx.error('Failed to remove cache file', { path: entry, error: err })\n          }\n        })\n\n        return Promise.all(promises)\n      },\n      { cacheCount: this.cache.size, cacheSize: this.cache.calculatedSize, gcCount: disposed.length }\n    )\n  }\n\n  get (key: string): PreviewFile | undefined {\n    return this.cache.get(key)\n  }\n\n  async put (key: string, value: PreviewFile): Promise<PreviewFile> {\n    let filePath = normalize(value.filePath)\n\n    if (key.length === 0) {\n      throw new Error('Invalid key')\n    }\n\n    const { size } = await stat(value.filePath)\n\n    if (!filePath.startsWith(this.cachePath)) {\n      try {\n        filePath = this.getFilePath(key)\n        await mkdir(dirname(filePath), { recursive: true })\n        await rename(value.filePath, filePath)\n      } catch (err) {\n        this.ctx.error('Failed to move file to cache', { filePath, error: err })\n        throw err\n      }\n    }\n\n    const entry = { ...value, filePath, size }\n    this.cache.set(key, entry)\n","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/pods/preview/src/cache.ts#L122-L158","documentation":"Error thrown by PreviewCache.put when the supplied cache key is an empty string. Empty keys cannot map to a stable file path under the cache directory, so the write is rejected early before touching the filesystem.","triggerScenarios":"Calling cache.put('', file) — typically because the hash/key derivation returned '' (e.g. hashing an empty URL, a failed digest, or a variable defaulting to empty before the call).","commonSituations":"Hash function silently returning empty on invalid input, using an unescaped/trimmed URL field that ends up empty, or wiring bugs where the key variable was never populated.","solutions":["Validate the key before calling put: if (!key) throw or skip the cache write","Fix upstream key derivation so it always yields a non-empty digest (check what is being hashed)","Guard put() at the call site and fall back to a no-cache path","Log the input that produced the empty key to trace the derivation bug"],"exampleFix":"// before\nawait cache.put(key, previewFile) // key === ''\n// after\nif (!key) {\n  console.warn('skip cache: empty key for', sourceUrl)\n} else {\n  await cache.put(key, previewFile)\n}","handlingStrategy":"validation","validationCode":"if (typeof key !== 'string' || key.length === 0) throw new Error('cache key required')","typeGuard":null,"tryCatchPattern":"try {\n  await cache.put(key, value)\n} catch (e) {\n  if (e.message === 'Invalid key') return null // bypass cache\n  throw e\n}","preventionTips":["Validate keys before every cache operation","Ensure hash functions cannot return empty output","Trace empty-key sources (untrimmed URL fields, unset variables)","Treat empty keys as cache bypass, not a crash"],"tags":["validation","cache","keys"],"backgroundTag":"invalid-cache-key","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}