Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

fix(collection): guard against collections with empty or missing source#438

Closed
humanbird wants to merge 1 commit into
nuxt-content:mainnuxt-content/nuxt-studio:mainfrom
humanbird:fix/collection-empty-source-guardshumanbird/nuxt-studio:fix/collection-empty-source-guardsCopy head branch name to clipboard
Closed

fix(collection): guard against collections with empty or missing source#438
humanbird wants to merge 1 commit into
nuxt-content:mainnuxt-content/nuxt-studio:mainfrom
humanbird:fix/collection-empty-source-guardshumanbird/nuxt-studio:fix/collection-empty-source-guardsCopy head branch name to clipboard

Conversation

@humanbird

Copy link
Copy Markdown

🔗 Linked issue

Resolves #425 (paired with upstream fix nuxt/content#3771)

❓ Type of change

  • 🐞 Bug fix (a non-breaking change that fixes an issue)

📚 Description

@nuxt/content v3 exposes an internal `info` collection whose `source` is serialized as an empty array (`source: []`) in the preview manifest (see nuxt/content#3767). Studio iterates every collection via `parseSourceBase`, `generateIdFromFsPath`, and `generateFsPathFromId`, which all assumed at least one `ResolvedCollectionSource` entry — so the editor crashed with:

```
TypeError: Cannot read properties of undefined (reading 'include')
at parseSourceBase (source.js)

TypeError: Cannot read properties of undefined (reading 'prefix')
at generateIdFromFsPath (collection.js)
```

The upstream payload fix (nuxt/content#3771) removes source-less collections from the preview manifest entirely, but these null guards are still the right shape defensively — Studio should tolerate any future source-less collection without corrupting the editor.

What changed

  • `parseSourceBase` now short-circuits to empty `fixed`/`dynamic` when the source (or its `include`) is missing.
  • `getCollectionSourceById` skips sources without `include` during matching instead of throwing.
  • `generateIdFromFsPath` falls back to `join(name, path)` when the collection has no source.
  • `generateFsPathFromId` returns the raw path when no source is given.

Tests

New cases added in `src/module/test/utils/source.test.ts` and `src/module/test/utils/collection.test.ts` covering each guarded path. `pnpm vitest run src/module/test/utils/source.test.ts src/module/test/utils/collection.test.ts` → 31/31 pass. Full suite: 184 tests pass; the 5 unrelated file-level failures (`document.test.ts`, `host.test.ts`, `draft-base.test.ts`, `compare.test.ts`) are caused by `nuxt-studio/app/utils` resolution in the playground setup on `main` and are reproducible without this PR.

📝 Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly. (no docs change needed — internal behavior only)

`@nuxt/content` v3 exposes an internal `info` collection whose `source`
is serialized as an empty array (`source: []`) in the preview manifest.
Studio iterates every collection via `parseSourceBase`,
`generateIdFromFsPath`, and `generateFsPathFromId`, which all assumed at
least one `ResolvedCollectionSource` entry and crashed with
`TypeError: Cannot read properties of undefined (reading 'include' |
'prefix')` as soon as the editor tried to list content.

The upstream payload fix is in nuxt/content#3771, but the guards here
are still the correct shape defensively — Studio should tolerate any
future source-less collection without corrupting the editor.

- `parseSourceBase` now short-circuits to empty `fixed`/`dynamic` when
  the source (or its `include`) is missing.
- `getCollectionSourceById` skips sources without `include` during
  matching instead of throwing.
- `generateIdFromFsPath` falls back to `join(name, path)` when the
  collection has no source.
- `generateFsPathFromId` returns the raw path when no source is given.

Resolves nuxt-content#425
@vercel

vercel Bot commented Apr 17, 2026

Copy link
Copy Markdown
Contributor

@humanbird is attempting to deploy a commit to the Nuxt Team on Vercel.

A member of the Team first needs to authorize it.

@larbish

larbish commented Apr 22, 2026

Copy link
Copy Markdown
Contributor

Hey @humanbird, thanks for the PR. However I'm not able to reproduce your case. Could you share a reproduction?

I've seen and approved nuxt/content#3771 that should be enough to fix what you're experiencing IMO.

If not, a better solution can be to filter at source (in host.ts and dev.host.ts) instead of handling cases in all utils.

@humanbird

Copy link
Copy Markdown
Author

Hey @larbish, you're right. Ran the unpatched nuxt-studio@1.6.0 utils against a real preview.mjs (17 collections, 111 files). All files that match a collection complete the fsPath → id → source → fsPath round-trip cleanly. The useContentCollections() filter in host.ts:57-66 plus the explicit name !== 'info' guard in list() handle every real path.

The only residual crash is a theoretical HMR path in host.dev.ts:57, which @nuxt/content doesn't actually trigger. With #3771 landing, the info collection won't even reach the preview manifest.

Closing as redundant. If it makes sense later to dedupe the filter into host.dev.ts too, happy to open a focused PR.

@humanbird humanbird closed this Apr 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TypeError: Cannot read properties of undefined (reading 'include') — collections with empty source[]

2 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.