Skip to content

fix(core): emit @@index for isIndexed: true, not an invalid inline @index - #859

Merged
borisno2 merged 1 commit into
mainfrom
claude/prisma-index-attribute-error-jtri3p
Aug 2, 2026
Merged

fix(core): emit @@index for isIndexed: true, not an invalid inline @index#859
borisno2 merged 1 commit into
mainfrom
claude/prisma-index-attribute-error-jtri3p

Conversation

@borisno2

@borisno2 borisno2 commented Aug 1, 2026

Copy link
Copy Markdown
Member

The bug

Prisma has no field-level @index attribute. @id, @unique, @default, @map, @relation, @updatedAt and @ignore are the entire field-level set — a non-unique index exists only as the model-level @@index([...]).

The text(), decimal() and calendarDay() builders appended @index to their field modifiers, so any config using isIndexed: true on a scalar produced a schema Prisma refuses to parse:

error: Attribute not known: "@index".
  -->  prisma/schema.prisma:567
   |
567 |   twilioSid    String @index

isIndexed: 'unique' was unaffected — inline @unique is valid.

relationship() has always got this right, emitting @@index([authorId]) via getPrismaRelation(). Only the scalar path was broken.

The fix

A field's index request now travels out-of-line. getPrismaType() gains an optional index?: boolean | 'unique', sitting beside the existing enumValues — already the channel by which a field asks for emission outside its own line. The generator collects these per list and emits them through the same pass that has always handled relationship foreign keys, so @@index([...]) for scalars and FKs is one code path.

Keeping the field the authority — rather than having the generator sniff isIndexed itself — preserves field self-containment, and lets a multi-column field (getPrismaColumns, ADR-0006), which has no single column matching its field name, decline rather than emit a fresh broken index.

isIndexed: 'unique' keeps emitting the inline @unique modifier. It has a valid field-level form and every schema generated to date contains it, so this channel carries only what cannot be written inline. Output for existing configs is byte-identical.

Why the tests didn't catch it

packages/core/tests/field-types.test.ts:106 asserted our own return value against our own convention, so it went green on output Prisma rejects — and a replacement asserting index: true would have the identical blind spot.

CI already has real Prisma gates (the scaffold generatedb:push guard, and the nightly per-example run). They never fired because no config in the repo used isIndexed: true on a scalar — the gate existed, the fixture didn't. Post.title in examples/blog now carries the option, so the nightly gate exercises a real scalar index, and the regenerated schema is committed as a visible artifact.

Verified end-to-end locally: pnpm generate (which runs prisma format and prisma generate, both of which parse the schema) → pnpm db:pushPost_title_idx present in the SQLite database.

Scope

Fixes the three builders that emit the broken attribute. integer, timestamp and select don't accept isIndexed at all — that's a compile error rather than a broken schema, and closing that gap is additive with its own design questions, so it's tracked separately rather than riding along in a fix.

No doc changes: the prose at docs/content/reference/fields-api.md:59/:623 already described @@index semantics correctly — the docs were ahead of the code, and the copy-pasteable examples at docs/content/concepts/field-types.md:100/:221 become valid as of this change.

Testing

  • Repointed field-types.test.ts to assert the index request and the absence of an inline attribute
  • Four generator tests: @@index for a scalar, for all three affected types, 'unique' still inline, and no index without the option
  • Confirmed the new tests are load-bearing by reintroducing the bug in the built core — they fail while the other 108 generator tests pass, reproducing the original blind spot exactly
  • Full suite green: 2,634 tests across 9 packages; pnpm lint 0 errors

Generated by Claude Code

…ndex

Prisma has no field-level `@index` attribute — `@id`, `@unique`, `@default`,
`@map`, `@relation`, `@updatedAt` and `@ignore` are the whole field-level set,
and a non-unique index exists only as the model-level `@@index([...])`. The
text(), decimal() and calendarDay() builders appended ` @index` to their field
modifiers, so any config using `isIndexed: true` on a scalar generated a schema
Prisma refuses to parse:

    error: Attribute not known: "@index".
      -->  prisma/schema.prisma:567
       |
    567 |   twilioSid    String @index

`isIndexed: 'unique'` was unaffected, since inline `@unique` is valid.

A field's index request now travels out-of-line: getPrismaType() gains an
optional `index`, sitting beside the existing `enumValues` — already the channel
by which a field asks for emission outside its own line. The generator collects
these per list and emits them through the same pass that has always handled
relationship foreign keys, so `@@index([...])` for scalars and FKs is one code
path. Keeping the field the authority (rather than having the generator sniff
`isIndexed` itself) preserves field self-containment and lets a multi-column
field, which has no single column matching its field name, decline.

`isIndexed: 'unique'` still emits the inline `@unique` modifier — it has a valid
field-level form, and every schema generated to date contains it — so this
channel carries only what cannot be written inline.

The existing unit test asserted our own return value against our own convention
and so went green on output Prisma rejects; it now asserts the index request and
the absence of an inline attribute. Post.title in examples/blog gains
`isIndexed: true`, which makes the already-existing nightly generate → db:push
gate exercise a real scalar index for the first time — that gate never fired
because no config in the repo used the option.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q142a6D7WsLJ39noXqrkN6
@changeset-bot

changeset-bot Bot commented Aug 1, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: b13ea79

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 9 packages
Name Type
@opensaas/stack-core Patch
@opensaas/stack-cli Patch
@opensaas/stack-auth Patch
@opensaas/stack-rag Patch
@opensaas/stack-storage Patch
@opensaas/stack-tiptap Patch
@opensaas/stack-ui Patch
@opensaas/stack-storage-s3 Patch
@opensaas/stack-storage-vercel Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Aug 1, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
stack-docs Ready Ready Preview Aug 1, 2026 11:08pm

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for Core Package Coverage (./packages/core)

Status Category Percentage Covered / Total
🟢 Lines 93.44% (🎯 65%) 1268 / 1357
🟢 Statements 91.91% (🎯 65%) 1365 / 1485
🟢 Functions 98.12% (🎯 62%) 209 / 213
🟢 Branches 83.37% (🎯 50%) 918 / 1101
File CoverageNo changed files found.
Generated in workflow #1571 for commit b13ea79 by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for UI Package Coverage (./packages/ui)

Status Category Percentage Covered / Total
🔵 Lines 76.72% 244 / 318
🔵 Statements 76.29% 251 / 329
🔵 Functions 69.15% 74 / 107
🔵 Branches 64.25% 160 / 249
File CoverageNo changed files found.
Generated in workflow #1571 for commit b13ea79 by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for CLI Package Coverage (./packages/cli)

Status Category Percentage Covered / Total
🔵 Lines 78.84% 1509 / 1914
🔵 Statements 78.53% 1570 / 1999
🔵 Functions 85.65% 209 / 244
🔵 Branches 67.03% 663 / 989
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/cli/src/generator/prisma.ts 94.73% 87.82% 100% 95.27% 63, 83, 105, 224-226, 266, 307, 370, 412
Generated in workflow #1571 for commit b13ea79 by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for Auth Package Coverage (./packages/auth)

Status Category Percentage Covered / Total
🔵 Lines 97.45% 115 / 118
🔵 Statements 97.52% 118 / 121
🔵 Functions 100% 38 / 38
🔵 Branches 92.85% 78 / 84
File CoverageNo changed files found.
Generated in workflow #1571 for commit b13ea79 by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for Storage Package Coverage (./packages/storage)

Status Category Percentage Covered / Total
🔵 Lines 78.57% 220 / 280
🔵 Statements 80.06% 245 / 306
🔵 Functions 86.07% 68 / 79
🔵 Branches 75.88% 214 / 282
File CoverageNo changed files found.
Generated in workflow #1571 for commit b13ea79 by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for RAG Package Coverage (./packages/rag)

Status Category Percentage Covered / Total
🔵 Lines 47.97% 355 / 740
🔵 Statements 48.14% 377 / 783
🔵 Functions 54.26% 70 / 129
🔵 Branches 42.55% 180 / 423
File CoverageNo changed files found.
Generated in workflow #1571 for commit b13ea79 by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for Storage S3 Package Coverage (./packages/storage-s3)

Status Category Percentage Covered / Total
🔵 Lines 100% 40 / 40
🔵 Statements 100% 40 / 40
🔵 Functions 100% 9 / 9
🔵 Branches 100% 19 / 19
File CoverageNo changed files found.
Generated in workflow #1571 for commit b13ea79 by the Vitest Coverage Report Action

@github-actions

github-actions Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Coverage Report for Storage Vercel Package Coverage (./packages/storage-vercel)

Status Category Percentage Covered / Total
🔵 Lines 100% 68 / 68
🔵 Statements 100% 71 / 71
🔵 Functions 100% 15 / 15
🔵 Branches 97.87% 46 / 47
File CoverageNo changed files found.
Generated in workflow #1571 for commit b13ea79 by the Vitest Coverage Report Action

@borisno2
borisno2 merged commit ebb4cd3 into main Aug 2, 2026
6 checks passed
@borisno2
borisno2 deleted the claude/prisma-index-attribute-error-jtri3p branch August 2, 2026 03:24
@github-actions github-actions Bot mentioned this pull request Aug 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants