{"record":{"id":"988e7f2ae131ca1a","repo":"mozilla/pdf.js","slug":"app-fs-is-read-only","errorCode":null,"errorMessage":"app.fs is read-only","messagePattern":"app\\.fs is read-only","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/scripting_api/app.js","lineNumber":249,"sourceCode":"  }\n\n  get fromPDFConverters() {\n    return [];\n  }\n\n  set fromPDFConverters(_) {\n    throw new Error(\"app.fromPDFConverters is read-only\");\n  }\n\n  get fs() {\n    return (this._fs ??= new Proxy(\n      new FullScreen({ send: this._send }),\n      this._proxyHandler\n    ));\n  }\n\n  set fs(_) {\n    throw new Error(\"app.fs is read-only\");\n  }\n\n  get language() {\n    return this._language;\n  }\n\n  set language(_) {\n    throw new Error(\"app.language is read-only\");\n  }\n\n  get media() {\n    return undefined;\n  }\n\n  set media(_) {\n    throw new Error(\"app.media is read-only\");\n  }\n","sourceCodeStart":231,"sourceCodeEnd":267,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/scripting_api/app.js#L231-L267","documentation":"app.fs is a lazily-created Proxy around a FullScreen helper used to drive fullscreen UI via the external send callback. Because it is viewer-internal state, PDF.js exposes it read-only and the setter throws. Assigning would sever the proxy wiring to the host viewer.","triggerScenarios":"Any assignment app.fs = ... in PDF JavaScript or API test code hits the throw at src/scripting_api/app.js:249.","commonSituations":"Scripts attempting to replace the fullscreen object with a mock; authors thinking fs is a configurable file-system handle (it is not).","solutions":["Use the returned FullScreen proxy's own methods/properties instead of reassigning app.fs.","Keep any test mocks at the underlying send/_externalCall layer, not by overwriting app.fs.","Read app.fs.* (e.g. transitions, click) for fullscreen control."],"exampleFix":"// before\napp.fs = myFullScreen;\n// after\napp.fs.click = false; // mutate properties, never reassign","handlingStrategy":"validation","validationCode":"// app.fs is a viewer-managed FullScreen proxy; read/use, never reassign.\nfunction withFullScreen(app, fn) {\n  const fs = app.fs;\n  if (!fs || typeof fs !== 'object') throw new Error('FullScreen unavailable');\n  return fn(fs);\n}","typeGuard":"const isFullScreenProxy = (v) =>\n  v != null && typeof v === 'object' && typeof v.constructor?.name === 'string';","tryCatchPattern":"try { /* code that may assign app.fs */ }\ncatch (e) { if (!/fs is read-only/.test(e.message)) throw e; }","preventionTips":["Operate on the returned proxy's own properties; never replace app.fs.","Mock fullscreen behavior at the send/_externalCall boundary in tests.","Remember fs = fullscreen, not a filesystem."],"tags":["scripting-api","read-only","fullscreen","proxy"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}