BarefootJS compiler errors follow the format BF + 3-digit code. Errors include source location and actionable suggestions.
#Error Format
error[BF001]: 'use client' directive required for components with createSignal
--> src/components/Counter.tsx:3:1
|
3 | import { createSignal } from '@barefootjs/dom'
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: Add 'use client' at the top of the file#Directive Errors (BF001–BF003)
#BF001 — Missing `"use client"` Directive
Trigger: A component uses reactive APIs (createSignal, createEffect, event handlers) but the file doesn't start with "use client".
// ❌ BF001
import { createSignal } from '@barefootjs/dom'
export function Counter() {
const [count, setCount] = createSignal(0)
return <button onClick={() => setCount(n => n + 1)}>{count()}</button>
}Fix: Add the directive at the top of the file:
// ✅ Fixed
"use client"
import { createSignal } from '@barefootjs/dom'
export function Counter() { ... }#BF002 — Invalid Directive Position
Trigger: "use client" is not the first statement in the file.
// ❌ BF002
import { createSignal } from '@barefootjs/dom'
"use client"Fix: Move the directive to the very first line (before any imports).
#BF003 — Client Component Importing Server Component
Trigger: A "use client" component imports from a file that doesn't have "use client".
Fix: Either add "use client" to the imported file, or restructure the import to only reference types/constants (which are safe to import).
#Signal Errors (BF010–BF012)
#BF010 — Unknown Signal Reference
Trigger: Code references a signal getter that wasn't declared in the component.
"use client"
export function Counter() {
return <span>{count()}</span> // ❌ count not declared
}Fix: Declare the signal:
const [count, setCount] = createSignal(0)#BF011 — Signal Used Outside Component
Trigger: createSignal is called at module level instead of inside a component function.
// ❌ BF011 — module-level signal
const [count, setCount] = createSignal(0)
export function Counter() {
return <span>{count()}</span>
}Fix: Move the signal inside the component:
export function Counter() {
const [count, setCount] = createSignal(0)
return <span>{count()}</span>
}#BF012 — Invalid Signal Usage
Trigger: Signal API used in an unsupported pattern.
#JSX Errors (BF020–BF023)
#BF020 — Invalid JSX Expression
Trigger: An expression in JSX braces can't be compiled.
#BF021 — Unsupported JSX Pattern
Trigger: An array method chain before .map() cannot be compiled to an SSR template. Unsupported patterns fall back to client-side evaluation.
#SSR-Compatible Chains
Only the following chain patterns are SSR-compiled as preprocessing before .map():
.filter().map().sort().map()/.toSorted().map().filter().sort().map().sort().filter().map()
Other method chains such as .reduce(), .slice(), .flatMap() are not detected and fall back to client-side evaluation.
#filter: Supported Predicates
Arrow function expression bodies composed of the following elements:
- Property access:
t.done,t.price - Literals:
'active',5,true - Comparison:
===,!==,>,<,>=,<= - Arithmetic:
+,-,*,/,% - Logical:
&&,||,! - Ternary:
cond ? a : b
// ✅ SSR-compilable
{items().filter(t => !t.done).map(t => <li>{t.name}</li>)}
{items().filter(t => t.price > 100 && t.active).map(t => <li>{t.name}</li>)}
// ❌ BF021 — typeof, function calls, nested higher-order methods are not supported
{items().filter(t => typeof t === 'string').map(...)}
{items().filter(t => customFn(t)).map(...)}
{items().filter(t => t.tags.some(tag => tag.featured)).map(...)}#sort: Supported Comparators
Only simple subtraction patterns of the form (a, b) => a.field - b.field:
// ✅ SSR-compilable
{items().sort((a, b) => a.price - b.price).map(...)} // ascending
{items().toSorted((a, b) => b.date - a.date).map(...)} // descending
// ❌ BF021 — block bodies, localeCompare, ternary operators, etc. are not supported
{items().sort((a, b) => { return a.price - b.price }).map(...)}
{items().sort((a, b) => a.name.localeCompare(b.name)).map(...)}#Workaround
Add /* @client */ to evaluate on the client side:
{/* @client */ todos().filter(t => t.items.some(i => i.done)).map(t => (
<li>{t.name}</li>
))}#BF022 — Invalid JSX Attribute
Trigger: An attribute value can't be compiled.
#BF023 — Missing Key in List
Trigger: A .map() loop doesn't provide a key prop for reconciliation.
// ❌ BF023
{items().map(item => <li>{item.name}</li>)}Fix:
// ✅ Add key
{items().map(item => <li key={item.id}>{item.name}</li>)}#Type Errors (BF030–BF031)
#BF030 — Type Inference Failed
Trigger: The compiler can't infer the type of a signal or expression for the target template language.
#BF031 — Props Type Mismatch
Trigger: A prop value doesn't match the declared type in the component's interface.
#Component Errors (BF040–BF043)
#BF040 — Component Not Found
Trigger: A referenced child component can't be resolved.
#BF041 — Circular Dependency
Trigger: Two components import each other.
#BF042 — Invalid Component Name
Trigger: Component name doesn't follow PascalCase convention.
#BF043 — Props Destructuring (Warning)
Trigger: Props are destructured in the function parameter, which captures values once and may lose reactivity.
// ⚠️ BF043
function Child({ count }: Props) {
return <span>{count}</span> // count is captured once
}warning[BF043]: Destructuring props in function parameters captures values once.
= help: Use `props.count` for reactive access, or suppress with // @bf-ignore props-destructuringFix options:
- Use direct props access:
function Child(props: Props) {
return <span>{props.count}</span> // Reactive
}- Suppress if intentional (static initial value):
// @bf-ignore props-destructuring
function Child({ initialCount }: Props) {
const [count, setCount] = createSignal(initialCount)
return <span>{count()}</span>
}#Suppressing Warnings
Use @bf-ignore to suppress specific warnings:
// @bf-ignore props-destructuring
function Component({ checked }: Props) {
// Warning suppressed
}Available rules:
| Rule ID | Error Code | Description |
|---|---|---|
props-destructuring |
BF043 | Props destructuring in function parameters |
#Error Code Quick Reference
| Code | Severity | Description |
|---|---|---|
| BF001 | Error | Missing "use client" directive |
| BF002 | Error | Invalid directive position |
| BF003 | Error | Client component importing server component |
| BF010 | Error | Unknown signal reference |
| BF011 | Error | Signal used outside component |
| BF012 | Error | Invalid signal usage |
| BF020 | Error | Invalid JSX expression |
| BF021 | Error | Unsupported JSX pattern for SSR |
| BF022 | Error | Invalid JSX attribute |
| BF023 | Error | Missing key in list |
| BF030 | Error | Type inference failed |
| BF031 | Error | Props type mismatch |
| BF040 | Error | Component not found |
| BF041 | Error | Circular dependency |
| BF042 | Error | Invalid component name |
| BF043 | Warning | Props destructuring breaks reactivity |