overleaf/overleaf · error

encryptJson is not implemented

Error message

encryptJson is not implemented

What it means

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.

Source

Thrown at libraries/access-token-encryptor/lib/js/AccessTokenEncryptor.js:20

const crypto = require('node:crypto')

const ALGORITHM = 'aes-256-ctr'

const cryptoHkdf = promisify(crypto.hkdf)
const cryptoRandomBytes = promisify(crypto.randomBytes)

class AbstractAccessTokenScheme {
  constructor(cipherLabel, cipherPassword) {
    this.cipherLabel = cipherLabel
    this.cipherPassword = cipherPassword
  }

  /**
   * @param {Object} json
   * @return {Promise<string>}
   */
  async encryptJson(json) {
    throw new Error('encryptJson is not implemented')
  }

  /**
   * @param {string} encryptedJson
   * @return {Promise<Object>}
   */
  async decryptToJson(encryptedJson) {
    throw new Error('decryptToJson is not implemented')
  }
}

class AccessTokenSchemeWithGenericKeyFn extends AbstractAccessTokenScheme {
  /**
   * @param {Buffer} salt
   * @return {Promise<Buffer>}
   */
  async keyFn(salt) {
    throw new Error('keyFn is not implemented')

View on GitHub (pinned to 28ad3b03b7)

Solutions

  1. Instantiate/extend a concrete scheme (e.g. AccessTokenSchemeV3 via AccessTokenEncryptor) instead of AbstractAccessTokenScheme
  2. In your subclass, override encryptJson(json) with a real implementation
  3. Use the public AccessTokenEncryptor facade (new AccessTokenEncryptor(settings).encryptJson(...)) rather than scheme classes directly

Example fix

// before
class MyScheme extends AbstractAccessTokenScheme {}
const s = new MyScheme(label, password)
await s.encryptJson(obj) // throws
// after
class MyScheme extends AbstractAccessTokenScheme {
  async encryptJson(json) {
    /* real encryption */
    return super.empty ?? ''
  }
}
Defensive patterns

Strategy: type-guard

Validate before calling

function isConcreteScheme(s) {
  return s && Object.getPrototypeOf(s) !== AbstractAccessTokenScheme.prototype && typeof s.encryptJson === 'function' && s.encryptJson !== AbstractAccessTokenScheme.prototype.encryptJson
}
if (!isConcreteScheme(scheme)) throw new Error('encryptJson called on abstract scheme')

Type guard

function canEncrypt(s) {
  return typeof s === 'object' && s !== null && s.encryptJson !== AbstractAccessTokenScheme.prototype.encryptJson
}

Try / catch

try {
  const encrypted = await scheme.encryptJson(obj)
} catch (err) {
  if (err.message === 'encryptJson is not implemented') {
    throw new Error('scheme misconfigured: abstract scheme used for encryption')
  }
  throw err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "NotImplementedError: Subclasses should override this method" / "must be implemented" — abstract method errors explained — this error's family across 40 libraries.

Related errors


AI-assisted analysis of overleaf/overleaf@28ad3b03b7 (2026-09-03). Data as JSON: /api/errors/308bd8e023ceebcc. Report an issue: GitHub.