saadeghi/daisyui · error · Error
Unsafe PR CSS in ${filePath}: ${reason}
Error message
Unsafe PR CSS in ${filePath}: ${reason} What it means
Thrown by unsafePrCss (called from assertSafePrCss) when the PR's component CSS contains content the preview pipeline refuses to render in Tailwind Play: a forbidden at-rule (@config, @plugin, @source), an external @import URL, or an external url() reference. The check is a security/safety gate before the CSS is shipped to play.tailwindcss.com.
Source
Thrown at packages/tailwind-play-share/pr-preview.mjs:289
}
function isNonLocalCssUrl(value) {
if (!value) return false
const normalized = normalizeCssUrl(value)
return normalized.startsWith("//") || /^[a-z][a-z0-9+.-]*:/i.test(normalized)
}
function normalizeCssUrl(value) {
return [...value.trim()]
.filter((character) => {
const codePoint = character.codePointAt(0)
return codePoint > 0x20 && codePoint !== 0x7f
})
.join("")
}
function unsafePrCss(filePath, reason) {
throw new Error(`Unsafe PR CSS in ${filePath}: ${reason}`)
}
export function assertSafePrCss(css, filePath = "component stylesheet") {
let index = 0
while (index < css.length) {
if (css.startsWith("/*", index)) {
index = consumeCssComment(css, index)
continue
}
if (css[index] === '"' || css[index] === "'") {
index = consumeCssString(css, index).end
continue
}
if (css[index] === "@") {
const atRule = consumeCssIdentifier(css, index + 1)
const name = atRule.value.toLowerCase()
if (forbiddenPrCssAtRules.has(name)) {View on GitHub (pinned to 42b09e637e)
Solutions
- Remove the forbidden @-rule or external URL from the component CSS in the PR.
- For @plugin/@config/@source, keep them in the root stylesheet, not in per-component CSS.
- Replace external url() references with relative or data: URLs if a URL is truly needed.
- Re-run; the error names the file and the reason so you can locate the offending line.
Example fix
/* before - packages/daisyui/src/components/btn.css */
@import url("https://cdn.example.com/btn.css");
.btn { background: url("https://cdn.example.com/bg.png"); }
/* after */
.btn { background: var(--btn-bg); } Defensive patterns
Strategy: validation
Validate before calling
import { assertSafePrCss } from "./pr-preview.mjs"
// Run the safety check on the changed CSS BEFORE invoking the full preview pipeline.
assertSafePrCss(changedCss, changedFilePath) Try / catch
try {
await generatePrPreview({ baseSha, headSha, output })
} catch (error) {
if (/^Unsafe PR CSS in /.test(error.message)) {
// the message names the file + reason; edit the CSS and re-push
}
throw error
} Prevention
- Keep @plugin/@config/@source and external URLs out of per-component CSS.
- Run assertSafePrCss in CI lint before the preview job.
- Treat the named file + reason in the message as the precise fix location.
When it happens
Trigger: assertSafePrCss walks the changed component CSS at the head SHA and, for any @-rule whose name is in forbiddenPrCssAtRules or any url()/@import resolving to a non-local scheme, calls unsafePrCss(filePath, reason).
Common situations: A PR adds `@plugin "..."`, `@config "..."`, `@source "..."`, `@import url("https://...")`, or `background: url("https://...")` inside packages/daisyui/src/components/*.css. These are blocked because Tailwind Play cannot safely load them.
Related errors
- No changed component CSS files were found between the suppli
- --base-sha is required
- --head-sha is required
- --timeout must be a positive number of milliseconds
- Provide HTML/CSS using arguments, files, or JSON on stdin
AI-assisted analysis of saadeghi/daisyui@42b09e637e (2026-08-13).
Data as JSON: /api/errors/d2cc0d76c944cab0.
Report an issue: GitHub.