> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wellapp.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# BlueprintPersistenceError

> BlueprintPersistenceError is a structured diagnostic sink for failures that occur during blueprint run persistence — replacing silent `logger.error` catches in

BlueprintPersistenceError is a structured diagnostic sink for failures that occur during blueprint run persistence — replacing silent `logger.error` catches in `BlueprintStorageService.persistStep` and the `runInBackground` helper. Each row records the phase of the blueprint pipeline that failed, the associated run ID, the workspace context (nullable for pre-auth failures), and the full error detail including message, type, stack, and an arbitrary JSON payload. Rows are pruned opportunistically after 30 days (\~1-in-20 writes trigger cleanup), mirroring the `connector_sync_diagnostics` retention pattern. The entity is append-only and owned entirely by the system — no user-facing PATCH route exists.

| Naming                          | Value                              |
| ------------------------------- | ---------------------------------- |
| Object                          | BlueprintPersistenceError          |
| Resource type (JSON:API `type`) | `blueprint_persistence_error`      |
| Collection / records root       | — <sub>(not a records root)</sub>  |
| REST base                       | `/v1/blueprint-persistence-errors` |
| Entity class                    | `BlueprintPersistenceError`        |

<Note>
  **Internal object.** Not currently exposed on the public REST API. The operations below describe the intended contract.
</Note>

## API operations

| Operation | Method & path                                  | Status     |
| --------- | ---------------------------------------------- | ---------- |
| List      | `GET /v1/blueprint-persistence-errors`         | 🟡 Planned |
| Retrieve  | `GET /v1/blueprint-persistence-errors/{id}`    | 🟡 Planned |
| Create    | `POST /v1/blueprint-persistence-errors`        | 🟡 Planned |
| Update    | `PATCH /v1/blueprint-persistence-errors/{id}`  | 🟡 Planned |
| Delete    | `DELETE /v1/blueprint-persistence-errors/{id}` | 🟡 Planned |

## Data model

### Attributes

| Field              | Type                                              | Required | Constraints                                                | Allowed values                                                                                                                                  | Description                                                                                                                                                                                                                                       |
| ------------------ | ------------------------------------------------- | -------- | ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| error\_id          | 🔒 system — UUID                                  | ✅ Yes    | unique, NOT NULL, default gen\_random\_uuid()              | —                                                                                                                                               | Public-facing unique identifier for this error row. Generated by the database via gen\_random\_uuid() at insert time. Used as the JSON:API `id`.                                                                                                  |
| blueprint\_run\_id | string (text)                                     | ✅ Yes    | NOT NULL                                                   | —                                                                                                                                               | Identifies the blueprint run that triggered this failure. Stored as free-form text matching the run's external identifier. Indexed for efficient per-run lookup.                                                                                  |
| phase              | enum (blueprint\_persistence\_error\_phase\_enum) | ✅ Yes    | NOT NULL; native Postgres enum stored as enum value string | upsert\_run \| increment\_step \| create\_step \| upload\_screenshot \| update\_run\_terminal \| persist\_step \| background\_runner \| handler | The pipeline phase in which the error occurred. Backed by a native Postgres enum. Indexed alongside created\_at for time-bucketed phase analysis.                                                                                                 |
| error\_type        | string (text)                                     | ⚪ No     | nullable                                                   | —                                                                                                                                               | Optional classification of the error class or exception type (e.g. the JavaScript error constructor name). Null when not captured.                                                                                                                |
| error\_message     | string (text)                                     | ✅ Yes    | NOT NULL                                                   | —                                                                                                                                               | The full human-readable error message from the caught exception.                                                                                                                                                                                  |
| stack              | string (text)                                     | ⚪ No     | nullable                                                   | —                                                                                                                                               | Full exception stack trace at the point of capture. Null when unavailable (e.g. non-Error throws).                                                                                                                                                |
| payload            | jsonb                                             | ⚪ No     | nullable, JSONB                                            | —                                                                                                                                               | Arbitrary structured context captured at the failure site — may include step index, run ID, workspace ID, or any other diagnostic fields relevant to the phase. Shape varies per phase.                                                           |
| created\_at        | 🔒 system — timestamptz                           | ✅ Yes    | NOT NULL, default now()                                    | —                                                                                                                                               | Timestamp set by the MikroORM onCreate hook (and defaulted to now() at the database level) when the error row is inserted. No updated\_at — this entity is append-only.                                                                           |
| deleted\_at        | 🔒 system — timestamptz                           | ⚪ No     | nullable                                                   | —                                                                                                                                               | Soft-delete timestamp. Set by the application retention logic (BlueprintPersistenceErrorService.write prunes rows older than 30 days on \~1/20 writes). Null means the row is active. Rows with deleted\_at set are filtered from normal queries. |

### Relationships

| Name      | Type               | Required | Description                                                                                                                                                                                                                                                                                                                                                                 |
| --------- | ------------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| workspace | to-one (ManyToOne) | ⚪ No     | The workspace this error belongs to. Nullable because some blueprint failure modes are caught before auth resolves a workspace (e.g. handler-level catch on a malformed request). Rows where workspace is null are intentionally invisible to the tenant `user` role in Hasura — only accessible via admin / Metabase / direct DB queries. References core\_api.workspaces. |

### System-computed

* error\_id: generated by gen\_random\_uuid() at the database level on insert; never supplied by callers
* created\_at: set by MikroORM onCreate hook (also defaulted to now() in the DDL); no updated\_at column exists — the entity is append-only
* deleted\_at: managed by application-level retention logic inside BlueprintPersistenceErrorService.write(), which prunes rows older than 30 days on approximately 1-in-20 writes; no scheduled job is required
* Retention sampling: the \~1/20 probabilistic pruning is designed to avoid a dedicated cron; the window may allow rows to survive slightly beyond 30 days
* Workspace nullability: workspace\_pk is nullable by design to capture pre-auth failures; Hasura user-role select\_permissions filter by workspace.workspace\_id, making null-workspace rows admin-only

## Example

```json theme={null}
{
  "data": {
    "type": "blueprint_persistence_error",
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "attributes": {
      "error_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "blueprint_run_id": "run_01HXYZ9876ABCDEF",
      "phase": "persist_step",
      "error_type": "EntityNotFoundError",
      "error_message": "Could not find BlueprintRun with id run_01HXYZ9876ABCDEF",
      "stack": "Error: Could not find BlueprintRun with id run_01HXYZ9876ABCDEF\n    at BlueprintStorageService.persistStep (/app/src/services/blueprint-storage.service.ts:142:13)",
      "payload": {
        "step_index": 3,
        "run_id": "run_01HXYZ9876ABCDEF",
        "workspace_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
      },
      "created_at": "2026-04-29T14:23:11.000Z",
      "deleted_at": null
    },
    "relationships": {
      "workspace": {
        "data": { "type": "workspace", "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479" }
      }
    }
  }
}
```

<sub>Source: `apps/api/src/database/entities/BlueprintPersistenceError.ts` · domain: automation · tier: Activity</sub>
