Skip to content

chore: Enhance schema compatibility checks and error handling#576

Merged
softmarshmallow merged 2 commits intomainfrom
canary
Mar 14, 2026
Merged

chore: Enhance schema compatibility checks and error handling#576
softmarshmallow merged 2 commits intomainfrom
canary

Conversation

@softmarshmallow
Copy link
Copy Markdown
Member

@softmarshmallow softmarshmallow commented Mar 13, 2026

  • Updated the CanvasPlayground component to improve error handling for document data, ensuring that incompatible files are quarantined to preserve user data.
  • Introduced a new schema compatibility check in the grida-canvas-io package, throwing an error if the file version is not compatible with the current schema version.
  • Added detailed documentation for the schema compatibility logic in the grida-canvas-schema package, clarifying versioning policy and compatibility rules.

These changes enhance data integrity and user experience by safeguarding against data corruption and ensuring compatibility with schema updates.

Summary by CodeRabbit

  • Bug Fixes

    • Loading now quarantines corrupted or otherwise unusable documents more aggressively; log wording updated to reflect "unusable" files.
  • New Features

    • Added schema compatibility checks to prevent loading incompatible files.
  • Tests

    • Updated tests to reference the canonical schema version rather than a hardcoded test value.

- Updated the CanvasPlayground component to improve error handling for document data, ensuring that incompatible files are quarantined to preserve user data.
- Introduced a new schema compatibility check in the grida-canvas-io package, throwing an error if the file version is not compatible with the current schema version.
- Added detailed documentation for the schema compatibility logic in the grida-canvas-schema package, clarifying versioning policy and compatibility rules.

These changes enhance data integrity and user experience by safeguarding against data corruption and ensuring compatibility with schema updates.
@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 13, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview, Comment Mar 14, 2026 7:00am
grida Ready Ready Preview, Comment Mar 14, 2026 7:00am
5 Skipped Deployments
Project Deployment Actions Updated (UTC)
code Ignored Ignored Mar 14, 2026 7:00am
legacy Ignored Ignored Mar 14, 2026 7:00am
backgrounds Skipped Skipped Mar 14, 2026 7:00am
blog Skipped Skipped Mar 14, 2026 7:00am
viewer Skipped Skipped Mar 14, 2026 7:00am

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 13, 2026

Walkthrough

Add a schema compatibility API and enforce schema version checks during file decoding; broaden OPFS load error handling to quarantine existing data for any non-"not found" failures and update the related log message.

Changes

Cohort / File(s) Summary
OPFS Error Handling
editor/grida-canvas-hosted/playground/playground.tsx
Expanded OPFS load error handling to quarantine on any failure except "not found"; updated log text from "unreadable" to "unusable"; removed prior transient/runtime fallback path.
Schema Validation & Decoding
packages/grida-canvas-io/format.ts, packages/grida-canvas-schema/grida.ts
Added public isSchemaCompatible(fileVersion) API and version parsing; format decoding now reads schemaVersion with nullish coalescing and throws if versions are incompatible.
Tests
packages/grida-canvas-io/__tests__/archive.test.ts
Replaced hardcoded test schema version with grida.program.document.SCHEMA_VERSION reference.

Sequence Diagram(s)

sequenceDiagram
  participant Client as Client
  participant OPFS as OPFS (storage)
  participant Decoder as Format Decoder
  participant Schema as Schema Checker
  participant Quarantine as Quarantine Store

  Client->>OPFS: openHandle(key)
  OPFS-->>Client: handle / not found / error
  alt handle returned
    Client->>OPFS: read(handle)
    OPFS-->>Client: data
    Client->>Decoder: decode(data)
    Decoder->>Schema: extract schemaVersion
    Schema->>Schema: isSchemaCompatible(fileVersion)
    alt compatible
      Decoder-->>Client: document
    else incompatible or Schema throws
      Client->>Quarantine: quarantine(handle, reason)
      Client-->>Client: surface error
    end
  else not found
    Client-->>Client: proceed with empty/new doc
  else error (other than not found)
    Client->>Quarantine: quarantine(handle, reason)
    Client-->>Client: surface error
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main objective: enhancing schema compatibility checks and improving error handling for OPFS loading and format validation across the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch canary
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 59aed69a6b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +502 to +503
} else {
// Any decode, structural validation, or state-init failure
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restrict OPFS quarantine to incompatible-document errors

This new else branch quarantines on every non-not found exception from the OPFS load path, so transient failures (for example Failed to read OPFS document.grida: ... from storage/runtime issues) and editor runtime errors from reset()/loadImages() now trigger opfs.quarantine(). Because quarantine() moves files and removes the originals (removeEntry in packages/grida-canvas-io/index.ts), a temporary failure can effectively hide otherwise valid user data and force fallback to an empty/default document. Quarantine should remain limited to decode/schema incompatibility signals, not all load-time exceptions.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
packages/grida-canvas-schema/grida.ts (1)

550-561: Consider failing fast if the current SCHEMA_VERSION is malformed.

If parseVersion(SCHEMA_VERSION) returns null due to a malformed constant (e.g., merge error or typo), all compatibility checks silently return false, causing every file to be rejected without clear indication of the root cause.

Since SCHEMA_VERSION is controlled internally, a parsing failure there indicates a bug in this codebase rather than invalid user input. Throwing an error would surface this issue immediately during development/testing.

Proposed fix
 export function isSchemaCompatible(fileVersion: string): boolean {
   const current = parseVersion(SCHEMA_VERSION);
+  if (!current) {
+    throw new Error(
+      `Invalid SCHEMA_VERSION constant: "${SCHEMA_VERSION}". Expected semver format.`
+    );
+  }
   const file = parseVersion(fileVersion);
-  if (!current || !file) return false;
+  if (!file) return false;

   if (current.major === 0) {

Based on learnings: "When breaking compatibility... readers should... reject with a clear error—do not silently misinterpret old data."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/grida-canvas-schema/grida.ts` around lines 550 - 561, The function
isSchemaCompatible currently treats a malformed internal SCHEMA_VERSION the same
as any bad input; change it so that after calling parseVersion(SCHEMA_VERSION)
you fail fast if current is null by throwing a clear error (e.g., include
SCHEMA_VERSION value) so developers see the broken constant; keep the existing
logic for when file parseVersion(fileVersion) returns null (return false) and
preserve the branch logic tied to current.major === 0 and post-1.0 behavior in
isSchemaCompatible.
editor/grida-canvas-hosted/playground/playground.tsx (1)

502-513: Scope quarantine to compatibility/decode errors only.

With Line 502 now treating all non-"not found" failures as quarantine-worthy, transient OPFS/read/runtime failures can quarantine otherwise valid data. Consider gating quarantine to known compatibility/decode failures and leaving other errors as recoverable/log-only.

Based on learnings: “Readers should use schema_version to decide whether to accept and decode normally, accept with best-effort degradation, migrate, or reject with a clear error.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@editor/grida-canvas-hosted/playground/playground.tsx` around lines 502 - 513,
The current catch treats any non-"not found" error as grounds to call
opfs?.quarantine(), which can quarantine valid data on transient I/O/runtime
failures; change the handler so only known
compatibility/decoding/schema-mismatch errors trigger opfs?.quarantine().
Concretely: in the catch that currently logs "OPFS document unusable ..." and
calls opfs?.quarantine(), detect specific error types or markers (e.g.,
error.name === "DecodeError" || error.code === "INCOMPATIBLE_SCHEMA" || a
schema_version mismatch after reading metadata) and call opfs?.quarantine() only
for those; for all other errors (I/O, transient, runtime) emit a warn/error log
with error details and fall back to the default document without quarantining.
Ensure you reference the same error variable and call opfs?.quarantine() only
under the compatibility/validation checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@editor/grida-canvas-hosted/playground/playground.tsx`:
- Around line 502-513: The current catch treats any non-"not found" error as
grounds to call opfs?.quarantine(), which can quarantine valid data on transient
I/O/runtime failures; change the handler so only known
compatibility/decoding/schema-mismatch errors trigger opfs?.quarantine().
Concretely: in the catch that currently logs "OPFS document unusable ..." and
calls opfs?.quarantine(), detect specific error types or markers (e.g.,
error.name === "DecodeError" || error.code === "INCOMPATIBLE_SCHEMA" || a
schema_version mismatch after reading metadata) and call opfs?.quarantine() only
for those; for all other errors (I/O, transient, runtime) emit a warn/error log
with error details and fall back to the default document without quarantining.
Ensure you reference the same error variable and call opfs?.quarantine() only
under the compatibility/validation checks.

In `@packages/grida-canvas-schema/grida.ts`:
- Around line 550-561: The function isSchemaCompatible currently treats a
malformed internal SCHEMA_VERSION the same as any bad input; change it so that
after calling parseVersion(SCHEMA_VERSION) you fail fast if current is null by
throwing a clear error (e.g., include SCHEMA_VERSION value) so developers see
the broken constant; keep the existing logic for when file
parseVersion(fileVersion) returns null (return false) and preserve the branch
logic tied to current.major === 0 and post-1.0 behavior in isSchemaCompatible.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 78a31937-c1ab-4e8f-ad5e-ed1d4d50571d

📥 Commits

Reviewing files that changed from the base of the PR and between de05d6f and 59aed69.

📒 Files selected for processing (3)
  • editor/grida-canvas-hosted/playground/playground.tsx
  • packages/grida-canvas-io/format.ts
  • packages/grida-canvas-schema/grida.ts

- Replaced hardcoded schema version string with dynamic reference to `grida.program.document.SCHEMA_VERSION` in the archive test file.

This change enhances maintainability by ensuring the test reflects the current schema version automatically.
@vercel vercel Bot temporarily deployed to Preview – blog March 14, 2026 06:57 Inactive
@vercel vercel Bot temporarily deployed to Preview – viewer March 14, 2026 06:57 Inactive
@vercel vercel Bot temporarily deployed to Preview – backgrounds March 14, 2026 06:57 Inactive
@softmarshmallow softmarshmallow changed the title Enhance schema compatibility checks and error handling chore: Enhance schema compatibility checks and error handling Mar 14, 2026
@softmarshmallow softmarshmallow merged commit 8d6c4ac into main Mar 14, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant