{"record":{"id":"308bd8e023ceebcc","repo":"overleaf/overleaf","slug":"encryptjson-is-not-implemented","errorCode":null,"errorMessage":"encryptJson is not implemented","messagePattern":"encryptJson is not implemented","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"libraries/access-token-encryptor/lib/js/AccessTokenEncryptor.js","lineNumber":20,"sourceCode":"const crypto = require('node:crypto')\n\nconst ALGORITHM = 'aes-256-ctr'\n\nconst cryptoHkdf = promisify(crypto.hkdf)\nconst cryptoRandomBytes = promisify(crypto.randomBytes)\n\nclass AbstractAccessTokenScheme {\n  constructor(cipherLabel, cipherPassword) {\n    this.cipherLabel = cipherLabel\n    this.cipherPassword = cipherPassword\n  }\n\n  /**\n   * @param {Object} json\n   * @return {Promise<string>}\n   */\n  async encryptJson(json) {\n    throw new Error('encryptJson is not implemented')\n  }\n\n  /**\n   * @param {string} encryptedJson\n   * @return {Promise<Object>}\n   */\n  async decryptToJson(encryptedJson) {\n    throw new Error('decryptToJson is not implemented')\n  }\n}\n\nclass AccessTokenSchemeWithGenericKeyFn extends AbstractAccessTokenScheme {\n  /**\n   * @param {Buffer} salt\n   * @return {Promise<Buffer>}\n   */\n  async keyFn(salt) {\n    throw new Error('keyFn is not implemented')","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/overleaf/overleaf/blob/28ad3b03b71cb4311decdcb55c36b33ec10d72db/libraries/access-token-encryptor/lib/js/AccessTokenEncryptor.js#L2-L38","documentation":"The AbstractAccessTokenScheme base class defines encryptJson as an abstract method that only throws. It exists so subclasses (like AccessTokenSchemeWithGenericKeyFn) must provide a real implementation. Hitting it means you called encryptJson on the abstract base class directly, or a subclass failed to override it.","triggerScenarios":"Calling encryptJson() on an instance of AbstractAccessTokenScheme itself, or on a custom subclass that extends AbstractAccessTokenScheme without overriding encryptJson. Also possible if a refactor renamed/replaced the concrete scheme so the base method is dispatched.","commonSituations":"A developer writes a new token scheme subclass and forgets to implement encryptJson; unit tests or stubs instantiate the abstract class directly; dependency-injection wires the base class instead of a concrete scheme.","solutions":["Instantiate/extend a concrete scheme (e.g. AccessTokenSchemeV3 via AccessTokenEncryptor) instead of AbstractAccessTokenScheme","In your subclass, override encryptJson(json) with a real implementation","Use the public AccessTokenEncryptor facade (new AccessTokenEncryptor(settings).encryptJson(...)) rather than scheme classes directly"],"exampleFix":"// before\nclass MyScheme extends AbstractAccessTokenScheme {}\nconst s = new MyScheme(label, password)\nawait s.encryptJson(obj) // throws\n// after\nclass MyScheme extends AbstractAccessTokenScheme {\n  async encryptJson(json) {\n    /* real encryption */\n    return super.empty ?? ''\n  }\n}","handlingStrategy":"type-guard","validationCode":"function isConcreteScheme(s) {\n  return s && Object.getPrototypeOf(s) !== AbstractAccessTokenScheme.prototype && typeof s.encryptJson === 'function' && s.encryptJson !== AbstractAccessTokenScheme.prototype.encryptJson\n}\nif (!isConcreteScheme(scheme)) throw new Error('encryptJson called on abstract scheme')","typeGuard":"function canEncrypt(s) {\n  return typeof s === 'object' && s !== null && s.encryptJson !== AbstractAccessTokenScheme.prototype.encryptJson\n}","tryCatchPattern":"try {\n  const encrypted = await scheme.encryptJson(obj)\n} catch (err) {\n  if (err.message === 'encryptJson is not implemented') {\n    throw new Error('scheme misconfigured: abstract scheme used for encryption')\n  }\n  throw err\n}","preventionTips":["Never instantiate AbstractAccessTokenScheme; always go through AccessTokenEncryptor","When subclassing, implement both encryptJson and decryptToJson (or extend AccessTokenSchemeWithGenericKeyFn and implement keyFn)","Add a smoke test that calls encryptJson/decryptToJson on the configured scheme at startup"],"tags":["javascript","abstract-method","unimplemented","library-misuse"],"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"}