{"record":{"id":"7af7a936ef4d4a55","repo":"oven-sh/bun","slug":"private-accessor-was-defined-without-a-setter","errorCode":null,"errorMessage":"Private accessor was defined without a setter","messagePattern":"Private accessor was defined without a setter","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"bench/snippets/private.mjs","lineNumber":18,"sourceCode":"import { bench, run } from \"../runner.mjs\";\n// This is a benchmark of the performance impact of using private properties.\n\nbench(\"Polyfillprivate\", () => {\n  \"use strict\";\n  var __classPrivateFieldGet =\n    (this && this.__classPrivateFieldGet) ||\n    function (receiver, state, kind, f) {\n      if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a getter\");\n      if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver))\n        throw new TypeError(\"Cannot read private member from an object whose class did not declare it\");\n      return kind === \"m\" ? f : kind === \"a\" ? f.call(receiver) : f ? f.value : state.get(receiver);\n    };\n  var __classPrivateFieldSet =\n    (this && this.__classPrivateFieldSet) ||\n    function (receiver, state, value, kind, f) {\n      if (kind === \"m\") throw new TypeError(\"Private method is not writable\");\n      if (kind === \"a\" && !f) throw new TypeError(\"Private accessor was defined without a setter\");\n      if (typeof state === \"function\" ? receiver !== state || !f : !state.has(receiver))\n        throw new TypeError(\"Cannot write private member to an object whose class did not declare it\");\n      return kind === \"a\" ? f.call(receiver, value) : f ? (f.value = value) : state.set(receiver, value), value;\n    };\n  var _Foo_state, _Foo_inc;\n  class Foo {\n    constructor() {\n      _Foo_state.set(this, 1);\n      _Foo_inc.set(this, 13);\n    }\n    run() {\n      let n = 1000000;\n      while (n-- > 0) {\n        __classPrivateFieldSet(\n          this,\n          _Foo_state,\n          __classPrivateFieldGet(this, _Foo_state, \"f\") + __classPrivateFieldGet(this, _Foo_inc, \"f\"),\n          \"f\",","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/bench/snippets/private.mjs#L1-L36","documentation":"The setter guard in the TypeScript __classPrivateFieldSet polyfill: when kind === 'a' (accessor) and no setter function `f` was passed, writing the private accessor throws this TypeError. It is the downlevel equivalent of assigning to a getter-only private accessor (`this.#x = value` where only `get #x()` is declared) — the field exists but writes are illegal, matching the native strict-mode TypeError.","triggerScenarios":"Downleveled TypeScript executing `this.#x = v` against a private accessor that declared only a getter (generated __classPrivateFieldSet with kind 'a' and no setter); or hand-calling the polyfill that way.","commonSituations":"Computed/read-only private state (caching lazy values) that later code tries to overwrite; refactoring a read-only accessor without updating all writers; libraries compiled to old targets where the compiler cannot catch cross-file writes.","solutions":["Add a `set #x(value)` alongside the getter so writes are legal","Route mutations through a method on the class that updates the underlying private field the getter reads from","If the value must truly be read-only, remove the write site — that is the intended design"],"exampleFix":"// before\nclass Foo {\n  get #x() { return this._x; }\n  set(v) { this.#x = v; } // TypeError: no setter\n}\n// after\nclass Foo {\n  get #x() { return this._x; }\n  set #x(v) { this._x = v; }\n  set(v) { this.#x = v; }\n}","handlingStrategy":"type-guard","validationCode":"// before writing a downleveled private accessor, confirm a setter exists\nif (kind === 'a' && typeof f !== 'function') throw new TypeError('cannot write getter-only private accessor');","typeGuard":"function hasPrivateSetter(kind, f) {\n  return kind !== 'a' || typeof f === 'function';\n}","tryCatchPattern":null,"preventionTips":["Pair every getter you write to with a setter, or route mutations through an explicit method","Use TypeScript's compile-time read-only detection: native get-only #accessors are flagged on assignment before emit","When consuming downleveled libraries, check their private accessor declarations before writing from your wrapper code"],"tags":["typescript","private-fields","private-accessors","downlevel-emit"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}