# Publish Errors

> Common publishing and validation failures when creating or updating pages

Canonical URL: https://fa7e86e3d553:3005/troubleshooting/publish-errors

Common publishing and validation failures when creating or updating pages.

## Symptom: "head.title is required"

Publishing fails with validation error about missing title.

### Cause

Blueprint is missing the `head.title` field.

### Fix

Always include a title in the `head` object.

```json
{
  "head": {
    "title": "Premium Leather Jackets | ShopName",
    "description": "Handcrafted leather jackets...",
    "keywords": ["leather", "jacket"]
  }
}
```

## Symptom: "sections must have at least 1 item"

Publishing fails with empty sections validation error.

### Cause

The `sections` array is empty.

### Fix

Include at least one section with an `id` and `html` field.

```json
{
  "sections": [
    {
      "id": "hero-main",
      "html": "<section>...</section>"
    }
  ]
}
```

## Symptom: "Duplicate section ID"

Publishing fails with duplicate ID error.

### Cause

Two or more sections have the same `id` value.

### Fix

Ensure each section has a unique, descriptive kebab-case ID.

```json
{
  "sections": [
    { "id": "hero-main", "html": "..." },
    { "id": "features-grid", "html": "..." },
    { "id": "testimonials", "html": "..." }
  ]
}
```

## Symptom: "Invalid island name"

Publishing fails with error about unknown island component.

### Cause

Using an `<lx-island name>` that doesn't exist in the catalog.

### Fix

Check valid island names at `/docs/resources/island-catalog` and use exact case-sensitive names.

```html
<!-- Valid -->
<lx-island name="ProductGallery">
  <script type="application/json">
{}
  </script>
</lx-island>

<!-- Invalid: ImageCarousel is not a registered island -->
<lx-island name="ImageCarousel">
  <script type="application/json">{}</script>
</lx-island>
```

## Symptom: "Blocked: fetch/eval/WebSocket"

Publishing fails with security error about blocked operations.

### Cause

Section JavaScript contains network operations or eval, which are blocked by the sandbox.

### Fix

Remove `fetch()`, `XMLHttpRequest`, `eval()`, `localStorage`, `WebSocket` from section JS. Use page-level `scripts[]` array for analytics/tracking instead.

```json
{
  "sections": [
    {
      "id": "hero",
      "html": "<section>...</section>",
      "js": "// Only DOM manipulation allowed here"
    }
  ],
  "scripts": [
    "https://www.googletagmanager.com/gtag/js?id=GA-123456"
  ]
}
```

## Symptom: "External script domain not allowed"

Publishing fails when adding external script.

### Cause

Script `src` URL is from a domain that's not on the allowlist.

### Fix

Only these domains are allowed for external scripts:

- `cdn.shopify.com`
- `cdn.judge.me`
- `cdn.klaviyo.com`
- `www.googletagmanager.com`
- `connect.facebook.net`
- `cdn.segment.com`
- `plausible.io`
- `unpkg.com`
- `cdn.jsdelivr.net`
- `cdnjs.cloudflare.com`

Self-host scripts not from these domains, or use inline `<script>` tags via section JS.

## Symptom: "Slug already exists"

Publishing fails with duplicate slug error.

### Cause

Another page in the workspace already uses that slug.

### Fix

Choose a different slug, or use `lexsis_drafts` with action
`page_update_section` to edit the existing page instead of creating a new one.

```json
{
  "slug": "leather-jackets-v2"
}
```

To update existing page instead, use the update tool with the existing page ID.

## Symptom: Publish Succeeds But Page Shows Old Content

Page publishes successfully but visiting the URL shows stale content.

### Cause

Edge cache has a 60-second TTL. Changes take up to 1 minute to propagate.

### Fix

Wait 60 seconds for cache to expire, or append a version query parameter for immediate preview:

```
https://storefront.trylexsis.com/my-page?v=2
```

Each new `v` value bypasses cache.

## Symptom: "workspace_id required"

API call fails with missing workspace_id error.

### Cause

The OAuth grant contains multiple authorized workspaces and the action did not
specify which one to use.

### Fix

Call `lexsis_workspace` with action `list`, ask the user to choose when more
than one workspace is returned, and pass that `workspace_id` to later actions.

```json
{
  "name": "lexsis_workspace",
  "arguments": {
    "action": "list",
    "args": {}
  }
}
```
