{"record":{"id":"e945444385e63341","repo":"basecamp/trix","slug":"trustedtypes-policy-policyname-could-not-b","errorCode":null,"errorMessage":"TrustedTypes policy ' + policyName + ' could not be created.","messagePattern":"TrustedTypes policy ' \\+ policyName \\+ ' could not be created\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"action_text-trix/app/assets/javascripts/trix.js","lineNumber":2156,"sourceCode":"    const ATTR_NAME = 'data-tt-policy-suffix';\n    if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {\n      suffix = purifyHostElement.getAttribute(ATTR_NAME);\n    }\n    const policyName = 'dompurify' + (suffix ? '#' + suffix : '');\n    try {\n      return trustedTypes.createPolicy(policyName, {\n        createHTML(html) {\n          return html;\n        },\n        createScriptURL(scriptUrl) {\n          return scriptUrl;\n        }\n      });\n    } catch (_) {\n      // Policy creation failed (most likely another DOMPurify script has\n      // already run). Skip creating the policy, as this will only cause errors\n      // if TT are enforced.\n      console.warn('TrustedTypes policy ' + policyName + ' could not be created.');\n      return null;\n    }\n  };\n  const _createHooksMap = function _createHooksMap() {\n    return {\n      afterSanitizeAttributes: [],\n      afterSanitizeElements: [],\n      afterSanitizeShadowDOM: [],\n      beforeSanitizeAttributes: [],\n      beforeSanitizeElements: [],\n      beforeSanitizeShadowDOM: [],\n      uponSanitizeAttribute: [],\n      uponSanitizeElement: [],\n      uponSanitizeShadowNode: []\n    };\n  };\n  /**\n   * Resolve a set-valued configuration option: a fresh set built from","sourceCodeStart":2138,"sourceCodeEnd":2174,"githubUrl":"https://github.com/basecamp/trix/blob/470040131122bd44e269b4de0f2e9557f90ec994/action_text-trix/app/assets/javascripts/trix.js#L2138-L2174","documentation":"DOMPurify, when running under browsers that enforce Trusted Types, tries to create a TrustedTypes policy (e.g. 'dompurify') to sign the HTML it returns. Policy creation is wrapped in try/catch; if it throws — most commonly because another DOMPurify instance or another script already created a policy with that exact name — the library logs this console.warn and returns null instead of throwing. Sanitization continues, but returned values will not be Trusted Types-wrapped, which can throw later if TT are enforced and unsanitized sinks are used.","triggerScenarios":"Trusted Types are enforced (or a CSP requires-trusted-types-for script is present) AND trustedTypes.createPolicy throws, typically because a policy named after the DOMPurify instance (e.g. 'dompurify') already exists without {createBehavior:'allow'}-style handling, or window.trustedTypes is present but createPolicy fails for the given name.","commonSituations":"Two copies of DOMPurify (or DOMPurify bundled both in trix.js and loaded separately) running on the same page; migrating an app to Trusted Types with an existing DOMPurify; a service worker / CSP requiring trusted types where a duplicate sanitizer already registered the policy name.","solutions":["Deduplicate: load only one copy of DOMPurify on the page (remove the separately bundled/CDN version if trix.js already includes it).","Supply a unique DOMPurify instance name via SANITIZE_DOM... or create your own policy with a unique name and pass it as TRUSTED_TYPES_POLICY so DOMPurify does not need to create one.","If the warning is expected (another policy is intentional), it is safe to ignore: sanitization still runs; only the TT wrapping is skipped.","If TT are enforced and you need signed output, ensure the policy exists and RETURN_TRUSTED_TYPE is true with a working TRUSTED_TYPES_POLICY."],"exampleFix":"// before: two DOMPurify copies on the page (CDN + bundled in trix)\n<script src=\"https://cdn.jsdelivr.net/npm/dompurify/dist/purify.min.js\"></script>\n// after: remove the standalone script and rely on the bundled copy,\n// or pre-create a uniquely-named policy and pass it:\nconst policy = trustedTypes.createPolicy('myapp-dompurify', {\n  createHTML: (s) => s,\n  createScriptURL: (s) => s\n});\nDOMPurify.sanitize(dirty, { TRUSTED_TYPES_POLICY: policy, RETURN_TRUSTED_TYPE: true });","handlingStrategy":"fallback","validationCode":"const ttAvailable = typeof window.trustedTypes !== 'undefined';\nlet policyExists = false;\ntry { trustedTypes.createPolicy('dompurify-probe', { createHTML: (s)=>s, createScriptURL: (s)=>s }); policyExists = true; } catch (e) { /* name taken or TT blocked */ }","typeGuard":"const canCreatePolicy = (w) => typeof w !== 'undefined' && !!w.trustedTypes && typeof w.trustedTypes.createPolicy === 'function';","tryCatchPattern":null,"preventionTips":["Ship exactly one copy of DOMPurify per page (audit bundles for duplicates).","Pre-create your own uniquely-named policy and pass it via TRUSTED_TYPES_POLICY.","Treat this console.warn as a smoke test when enabling Trusted Types in CSP.","Test the app with require-trusted-types-for 'script' in a staging CSP before rollout."],"tags":["dompurify","trusted-types","policy-creation","duplicate-script"],"backgroundTag":"trusted-types-policy-conflict","analyzedSha":"470040131122bd44e269b4de0f2e9557f90ec994","analyzedAt":"2026-09-02T10:19:15.878Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T16:17:10.729Z"}