{"record":{"id":"f53a014b13113adb","repo":"overleaf/overleaf","slug":"filedata-tostats-not-implemented","errorCode":null,"errorMessage":"FileData: toStats not implemented","messagePattern":"FileData: toStats not implemented","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"libraries/overleaf-editor-core/lib/file_data/index.js","lineNumber":88,"sourceCode":"    return new LazyStringFileData(\n      blob.getHash(),\n      rangesBlob?.getHash(),\n      stringLength\n    )\n  }\n\n  /**\n   * @returns {RawFileData}\n   */\n  toRaw() {\n    throw new Error('FileData: toRaw not implemented')\n  }\n\n  /**\n   * @returns {Record<string, number>}\n   */\n  toStats() {\n    throw new Error('FileData: toStats not implemented')\n  }\n\n  /**\n   * @see File#getHash\n   * @return {string | null | undefined}\n   */\n\n  getHash() {\n    return null\n  }\n\n  /**\n   * @see File#getHash\n   * @return {string | null | undefined}\n   */\n  getRangesHash() {\n    return null\n  }","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/overleaf/overleaf/blob/28ad3b03b71cb4311decdcb55c36b33ec10d72db/libraries/overleaf-editor-core/lib/file_data/index.js#L70-L106","documentation":"toStats() returns a Record<string, number> of file statistics (e.g. byte/string lengths) and is another abstract stub on the FileData base class. Every concrete subclass must override it; hitting the stub means the receiver has no stats implementation. Throwing keeps stats consumers from reading meaningless defaults like 0.","triggerScenarios":"Calling toStats() on a bare new FileData() or on a custom subclass that overrides toRaw/edit but not toStats; invoking it through File wrapper methods on such an instance.","commonSituations":"Custom or test-double FileData subclasses; version drift where a new abstract method (toStats) was added and older subclasses in your codebase were not updated; directly instantiating the base class.","solutions":["Add a toStats() override to the offending subclass returning its numeric stats (e.g. {byteLength, stringLength}).","Replace ad-hoc subclass instances with the library's concrete classes that already implement toStats.","Update subclasses after upgrading overleaf-editor-core to satisfy any newly added abstract members."],"exampleFix":"// before\nclass CustomFileData extends FileData {}\n// after\nclass CustomFileData extends FileData {\n  toStats() {\n    return { byteLength: this.getByteLength() || 0 }\n  }\n}","handlingStrategy":"type-guard","validationCode":"if (FileData.prototype.toStats === fileData.toStats) {\n  throw new Error(fileData.constructor.name + ' does not implement toStats')\n}","typeGuard":"const implementsToStats = (fd) =>\n  fd instanceof FileData && FileData.prototype.toStats !== fd.toStats","tryCatchPattern":"let stats\ntry {\n  stats = fileData.toStats()\n} catch (err) {\n  if (err.message === 'FileData: toStats not implemented') {\n    stats = {}\n  } else {\n    throw err\n  }\n}","preventionTips":["Override all abstract methods when extending FileData, not just the ones currently used.","Re-run subclass test suites after upgrading overleaf-editor-core (new abstract methods may appear).","Prefer composition over subclassing FileData for test doubles."],"tags":["abstract-method","subclassing","overleaf-editor-core"],"backgroundTag":"abstract-method-not-implemented","analyzedSha":"28ad3b03b71cb4311decdcb55c36b33ec10d72db","analyzedAt":"2026-09-03T02:10:22.807Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T07:17:11.731Z"}