# WEB Error Handling And Troubleshooting

This document explains how to diagnose and fix common WEB compiler and CLI errors.

Use it when:

- a `.web` file fails to compile
- the compiler message is technically correct but you want the practical fix
- you are unsure whether something belongs in DOM scope, CSS scope, `define`, `::attrs`, `::head`, or `::script`
- the CLI resolves a target differently than you expected

## 1. How To Read Modern Compiler Errors

The compiler now tries to explain errors in a developer-friendly format.

A typical error includes:

- the original failure message
- `Source:` with file name and `line:column`
- `Phase:` such as `lexing`, `parsing`, `semantic analysis`, `HTML preparation`, or `CSS preparation`
- `Violation:` which explains the rule that was broken
- `Found:` which shows the token or character that caused the failure
- `How to fix:` with the concrete correction to make
- `Example:` with a valid pattern
- `Context:` with a code frame and caret

Example:

```text
Expected ";" after assignment (line 8, column 3)
Source: home.web:8:3
Phase: parsing
Violation: WEB terminates declarations, assignments, and attribute entries with a semicolon.
Found: token IDENTIFIER "pageTitle"
How to fix: Add `;` at the end of the current statement before starting the next statement or closing the block.
Example: heroTitle.textContent = "Hello";
Context:
  7 |   pageTitle.textContent = "Missing semicolon"
> 8 |   pageTitle.color = "#223344";
    |   ^
  9 | }
```

## 2. Fast Triage Checklist

When a file fails, check these first:

1. Did every assignment end with `;`?
2. Did every `{` get a matching `}`?
3. Did you put strings, URLs, and hex colors in quotes?
4. Did you keep variables, type declarations, and `extends` declarations inside one top-level `define { ... }` block?
5. Did you put only HTML attributes inside `::attrs`?
6. Did you keep `::head` and `::script` at the top level?
7. Did you use only valid value types: string, template literal, number, percentage, identifier, variable, or `js` literal?
8. If using the CLI, did the target actually resolve to one or more `.web` files?

## 3. Common Syntax Errors

### Missing semicolon

Symptom:

- `Expected ";" after assignment`
- `Expected ";" after declaration`
- `Expected ";" after variable declaration`

Why it happens:

- WEB statements are terminated with semicolons.

Wrong:

```web
heroTitle.textContent = "Hello"
heroTitle.color = "#223344";
```

Right:

```web
heroTitle.textContent = "Hello";
heroTitle.color = "#223344";
```

### Missing `=`

Symptom:

- `Expected "=" after ...`

Why it happens:

- Assignments in WEB use `=`, not `:`.

Wrong:

```web
heroTitle.color: "#223344";
```

Right:

```web
heroTitle.color = "#223344";
```

### Missing `{` or `}`

Symptom:

- `Expected "{" after ...`
- `Expected "}" after ...`
- `Unterminated ...`

Why it happens:

- Block headers must open with `{`
- every block must close with `}`

Wrong:

```web
heroSection
  padding = "2rem";
```

Right:

```web
heroSection {
  padding = "2rem";
}
```

### Unquoted values that need punctuation or spaces

Symptom:

- `Unexpected character "#"`
- `Unexpected value token ...`

Why it happens:

- WEB accepts simple identifier values like `Hello`
- but values containing punctuation or spaces, such as `#223344`, `/docs`, or `Hello world`, must be quoted
- quoting URLs, prose, and hex colors is the safest default

Wrong:

```web
heroLink.href = /docs;
heroTitle.color = #223344;
heroTitle.textContent = Hello world;
```

Right:

```web
heroLink.href = "/docs";
heroTitle.color = "#223344";
heroTitle.textContent = "Hello world";
```

### Broken dot notation

Symptom:

- `Expected an identifier after "."`

Why it happens:

- every `.` in a path must be followed by a normal identifier

Wrong:

```web
pageMain..heroTitle.textContent = "Hello";
```

Right:

```web
pageMain.heroTitle.textContent = "Hello";
```

### Unterminated strings or literals

Symptom:

- `Unterminated string literal`
- `Unterminated template literal`
- `Unterminated JavaScript inject literal`

Why it happens:

- the closing quote or backtick is missing

Wrong:

```web
heroTitle.textContent = "Hello;
```

Right:

```web
heroTitle.textContent = "Hello";
```

Wrong:

```web
heroCopy.innerHTML = js`return "<strong>Hello</strong>";
```

Right:

```web
heroCopy.innerHTML = js`return "<strong>Hello</strong>";`;
```

## 4. Block Placement Errors

### `define { ... }` in the wrong place

Symptom:

- `The define { ... } block must appear once at the top of the file before any rules.`
- `Only one top-level define { ... } block is allowed.`

Why it happens:

- WEB allows only one top-level `define` block
- it must come before normal element rules

Wrong:

```web
pageMain.padding = "2rem";

define {
  @gap = "1rem";
}
```

Right:

```web
define {
  @gap = "1rem";
}

pageMain.padding = @gap;
```

### Variables, type declarations, or `extends` outside `define`

Symptom:

- `Variables must be declared inside a top-level define { ... } block before any rules.`
- `Type declarations must be declared inside a top-level define { ... } block before any rules.`
- `Style inheritance must be declared inside a top-level define { ... } block before any rules.`

Why it happens:

- these declarations are only legal inside the single top-level `define` block

Wrong:

```web
@gap = "1rem";
Button primaryButton;
primaryButton extends buttonBase;
```

Right:

```web
define {
  @gap = "1rem";
  Button primaryButton;
  primaryButton extends buttonBase;
}
```

### `::attrs` used in the wrong scope

Symptom:

- `::attrs blocks must be nested directly inside an element scope.`
- `::attrs blocks only support direct HTML attribute assignments like href = "/docs";`

Why it happens:

- `::attrs` is only for HTML attributes
- it must live inside a normal DOM element block
- it cannot contain nested blocks, CSS properties, or content properties

Wrong:

```web
styles {
  card {
    ::attrs {
      href = "/docs";
    }
  }
}
```

Wrong:

```web
docsLink {
  ::attrs {
    color = "#223344";
    textContent = "Docs";
  }
}
```

Right:

```web
docsLink {
  textContent = "Docs";

  ::attrs {
    href = "/docs";
    ariaLabel = "Open docs";
  }
}
```

### `::head` and `::script` nested inside element scopes

Symptom:

- `::head blocks must be declared at the top level outside element, style, pseudo, and media scopes.`
- `::script blocks must be declared at the top level outside element, style, pseudo, and media scopes.`

Why it happens:

- these blocks describe document-level output, not a single DOM node

Wrong:

```web
pageMain {
  ::head {
    meta {
      name = "description";
      content = "Demo";
    }
  }
}
```

Right:

```web
::head {
  meta {
    name = "description";
    content = "Demo";
  }
}
```

### Misusing `styles`, `::pseudo`, or `::media`

Symptom:

- `styles blocks only support CSS properties and raw assignments`
- `Pseudo blocks and media queries only support CSS properties and raw assignments`

Why it happens:

- CSS scopes are for CSS only
- they do not accept `textContent`, `innerHTML`, or HTML attributes

Wrong:

```web
card {
  styles {
    title {
      textContent = "Hello";
    }
  }
}
```

Right:

```web
card {
  title {
    textContent = "Hello";
  }

  styles {
    title {
      color = "#223344";
    }
  }
}
```

### Global style blocks in the wrong place

Symptom:

- `Global style blocks using "*" or "html" must be declared at the top level or inside a top-level ::media block without a parent selector.`

Why it happens:

- `html { ... }` and `* { ... }` are reserved for global CSS
- they are not element blocks

Wrong:

```web
pageMain {
  html {
    backgroundColor = "#101522";
  }
}
```

Right:

```web
html {
  backgroundColor = "#101522";
}
```

## 5. Common Semantic Errors And Misconceptions

### Misconception: `extends` creates DOM inheritance

Reality:

- `derivedName extends baseName;` only affects CSS inheritance in the compiler
- it does not create parent-child HTML structure

Wrong assumption:

```web
define {
  primaryButton extends buttonBase;
}
```

This does not create a nested node or shared DOM structure.

Use real nesting for DOM structure:

```web
pageMain {
  primaryButton {
    textContent = "Launch";
  }
}
```

### Misconception: `styles { ... }` creates HTML nodes

Reality:

- `styles { ... }` only contributes CSS
- if a node exists only inside `styles`, it does not create HTML output

If you want HTML, define the node in normal DOM scope:

```web
card {
  title {
    textContent = "Hello";
  }
}
```

### Unknown variable

Symptom:

- `Unknown variable "@accent"`

Why it happens:

- the variable was never declared
- the variable name was misspelled

Fix:

- declare it inside `define`
- use the exact same name everywhere

Right:

```web
define {
  @accent = "#94a7ca";
}

heroTitle.color = @accent;
```

### Circular references

Symptom:

- `Circular variable reference involving "..."`
- `Circular type inheritance involving "..."`
- `Circular style inheritance involving "..."`

Why it happens:

- the compiler detected a loop

Fix:

- break the cycle so the chain resolves in one direction only

Wrong:

```web
define {
  @a = @b;
  @b = @a;
}
```

Right:

```web
define {
  @a = "#94a7ca";
  @b = @a;
}
```

### Void elements cannot contain content

Symptom:

- `Void element <...> cannot contain content or children for "..."`

Why it happens:

- some HTML tags cannot contain children or text
- examples include `img`, `input`, `meta`, and `link`

Fix:

- move text or children to a non-void element
- keep the void element for attributes only

Wrong:

```web
heroImage {
  textContent = "Preview";
}
```

Right:

```web
heroImage {
  ::attrs {
    src = "/hero.png";
    alt = "Preview";
  }
}
```

### Misconception: `js\`...\`` runs in the browser

Reality:

- `js\`...\`` runs at compile time in Node
- it does not create browser-side runtime logic by itself

Use `::script` when you need emitted browser JavaScript:

```web
::script {
  src = "/assets/app.js";
}
```

## 6. Keyframes And Animation Mistakes

### Invalid keyframe stage

Symptom:

- `Expected a keyframe stage such as "from", "to", or "50%"`

Why it happens:

- only `from`, `to`, or percentage stages are valid

Wrong:

```web
::keyframes fadeIn {
  start {
    opacity = 0;
  }
}
```

Right:

```web
::keyframes fadeIn {
  from {
    opacity = 0;
  }

  to {
    opacity = 1;
  }
}
```

## 7. Raw CSS Misunderstandings

### Broken `raw` CSS block

Symptom:

- `Unterminated CSS block in raw template literal`
- `Unterminated quoted text in raw CSS`
- `Unterminated CSS block comment in raw template literal`

Why it happens:

- the CSS inside the template literal is malformed

Fix:

- treat the inside of `raw = \`...\`;` as real CSS syntax
- make sure braces, quotes, and comments are balanced

Right:

```web
primaryButton {
  raw = `
    transition: transform 0.2s ease;
    &:hover { transform: translateY(-2px); }
  `;
}
```

## 8. CLI Errors And Common Misconceptions

### `web .` is not recursive

Common misconception:

- `web .` will compile every `.web` file in every nested folder

Reality:

- `web .` compiles only direct `.web` files in the current directory

If you want nested files, target them explicitly:

```bash
web ./code/*
```

### Bare names only resolve to `name.web`

Common misconception:

- `web home` might resolve `home.txt`, `home.html`, or a directory

Reality:

- bare-name convenience only checks for `home.web`

### `web init` will not overwrite existing scaffold files

Common misconception:

- `web init` should replace whatever `index.web`, `index.html`, `index.css`, or `web-lang-agents.md` already exist in the directory

Reality:

- the init command refuses to overwrite those scaffold files
- this protects existing work from being replaced by the starter template

Fix:

- run `web init` in a clean directory
- or move/remove the conflicting files before you try again

### `web init` expects a directory target

Common misconception:

- `web init website.txt`
- `web init existing-file`

Reality:

- the init command accepts one directory target, not a file target
- if the path already exists and is a file, the CLI stops before scaffolding

Fix:

- pass `.` for the current directory
- pass a directory path like `website` or `./projects/website`
- rename or remove the conflicting file if you meant to use that path as a directory

### `web watch` only accepts one resolved `.web` source

Common misconception:

- `web watch .`
- `web watch ./pages/*`
- `web watch home.web about.web`

Reality:

- the watch command currently watches one resolved `.web` source at a time

Fix:

- point the watch command at a single file
- use `web home.web` or `web ./pages/*` for one-off multi-file compiles
- start a second watch session in another terminal if you need to watch a different file

### `web-lang-screenshots` is created in the current working directory

Common misconception:

- screenshots are written next to the source file

Reality:

- screenshots are written into `./web-lang-screenshots` rooted at the directory where you ran the CLI

Fix:

- look for screenshots in the current working directory first
- if the source file is inside the current working directory, check for preserved subfolders inside `web-lang-screenshots`
- remember that filenames also include readable timestamps

### `web watch` stopped because there was no recent activity

Common misconception:

- the watch session should stay alive forever if screenshots are still being captured

Reality:

- the watch session shuts itself down after 1 hour with no recent source activity
- periodic screenshots do not count as source activity

Fix:

- restart the watch command when you are ready to continue
- keep editing the watched source if you want the session to remain active
- read the exit summary: it reports the idle threshold, last source activity time, and recent build results

### Screenshot capture failed in `web screenshot` or `web watch -s`

Why it happens:

- package dependencies have not been installed yet in the local checkout
- the headless browser could not start in the current environment
- the compiled HTML was generated, but the render step failed afterward

Fix:

- run `npm install` inside the package checkout
- try `web home.web` first to confirm compilation succeeds without the screenshot step
- then rerun `web screenshot home.web` or `web watch home.web -s`
- if the CLI prints a screenshot error, read the full message because it is reported separately from compile errors

### `No .web files found for "..."` or `No WEB source matched "..."` 

Why it happens:

- the path does not exist
- the directory has no direct `.web` files
- the glob matched something other than `.web` files

Fix:

- check your current working directory
- verify the target path exists
- verify the file actually ends with `.web`
- use a more specific glob if needed

## 9. Wrong vs Right Mental Model

If something feels confusing, use this mapping:

- normal block like `pageMain { ... }`
  - creates HTML structure and can also carry styles
- path assignment like `pageMain.heroTitle.color = "#223344";`
  - targets a real node path and produces CSS or content depending on the property
- `styles { ... }`
  - CSS only
- `::hover`, `::before`, `::media`
  - CSS only
- `::attrs`
  - HTML attributes only
- `::head`
  - document head entries only
- `::script`
  - emitted script tags only
- `define`
  - declarations only

## 10. Recommended Debug Workflow

When a file breaks:

1. Read the `Phase:` line to see whether this is syntax, semantics, HTML generation, or CSS generation.
2. Read `Violation:` before changing code. It explains the actual rule.
3. Look at `Found:` to see what token or character the compiler was actually reading.
4. Use the `Context:` frame, not just the line number. The actual problem is often one line earlier.
5. Fix one error at a time and re-run the compiler.
6. If the CLI target failed before compilation, confirm the target resolves to a real `.web` file.

## 11. When In Doubt

If you are unsure where code belongs, start from the simplest legal structure:

```web
define {
  @accent = "#94a7ca";
  Main pageMain;
  Heading1 heroTitle;
}

pageMain {
  padding = "2rem";

  heroTitle {
    textContent = "Hello";
    color = @accent;
  }
}
```

Then add:

- `::attrs` for attributes
- `styles` or `::pseudo` for CSS-only variations
- `::head` for metadata
- `::script` for emitted browser scripts
- `raw` only when normal WEB syntax is not enough
