slidevjs/slidev · critical · Error
[slidev] Cannot find roots without entry
Error message
[slidev] Cannot find roots without entry
What it means
Thrown by getRoots(entry?) when rootsInfo is still null and no entry argument was supplied. getRoots memoizes after the first successful call; the very first call must receive an entry path so it can derive userRoot, detect global install mode, and locate @slidev/client. Subsequent calls return the cache and need no entry.
Source
Thrown at packages/slidev/node/resolver.ts:434
return current
if (await hasWorkspacePackageJSON(current))
return current
const dir = dirname(current)
// reach the fs root
if (!dir || dir === current)
return root
return searchForWorkspaceRoot(dir, root)
}
let rootsInfo: RootsInfo | null = null
export async function getRoots(entry?: string): Promise<RootsInfo> {
if (rootsInfo)
return rootsInfo
if (!entry)
throw new Error('[slidev] Cannot find roots without entry')
const userRoot = dirname(entry)
isInstalledGlobally.value
= slash(relative(userRoot, process.argv[1])).includes('/.pnpm/')
// pnpm v11 isolated globals don't expose a `.pnpm/` segment in argv[1]
// and aren't detected by `is-installed-globally` (which only knows npm
// and yarn). The cli's bin is symlinked into an install-group
// `node_modules/` that's outside the user's workspace, so use that as
// the global-mode signal.
|| (invocationNodeModules != null
&& slash(relative(userRoot, invocationNodeModules)).startsWith('..'))
|| (await import('is-installed-globally')).default
const clientRoot = await findPkgRoot('@slidev/client', cliRoot, true)
const closestPkgRoot = dirname(await findClosestPkgJsonPath(userRoot) || userRoot)
const userPkgJson = await getUserPkgJson(closestPkgRoot)
const userWorkspaceRoot = await searchForWorkspaceRoot(closestPkgRoot)
rootsInfo = {
cliRoot,
clientRoot,View on GitHub (pinned to 0d798ace58)
Solutions
- Call getRoots(entryPath) once at startup with the absolute path to the entry markdown before any code that may call getRoots() with no argument.
- Ensure the CLI entry flow resolves the entry file (resolveEntry) and forwards it into getRoots.
- In tests/programmatic use, seed rootsInfo by calling getRoots with a fixture entry path first.
Example fix
// before: first call without entry
const roots = await getRoots() // throws
// after: seed with the entry on first call
const roots = await getRoots(resolve('/abs/path/to/slides.md'))
// later calls can omit entry:
const same = await getRoots() Defensive patterns
Strategy: validation
Validate before calling
let rootsSeeded = false
async function ensureRoots(entry: string): Promise<RootsInfo> {
if (!rootsSeeded) {
await getRoots(entry) // seed the cache on first call
rootsSeeded = true
}
return getRoots() // subsequent calls are safe
}
// at startup:
await ensureRoots(resolve('/abs/path/to/slides.md')) Type guard
function entryProvided(entry: string | undefined): entry is string {
return typeof entry === 'string' && entry.length > 0
} Try / catch
try {
return await getRoots()
} catch (e) {
if (e instanceof Error && e.message === '[slidev] Cannot find roots without entry') {
if (!entryPath) throw e
return await getRoots(entryPath) // seed on demand
}
throw e
} Prevention
- Call getRoots(absoluteEntryPath) once during boot, before any lazy resolver use.
- Forward the resolved entry from the CLI flow into all getRoots calls.
- In tests, seed rootsInfo with a fixture entry path in setup.
- Order module initialization so the entry is known before plugins call getRoots().
When it happens
Trigger: Calling getRoots() (no argument) before any caller has called getRoots(entryPath) to seed the cache. Happens when an API consumer (e.g. importOptionalDependency) invokes getRoots lazily without the boot path forwarding an entry.
Common situations: Programmatic use of Slidev APIs that omits the entry bootstrap; a plugin that calls getRoots() during module init, before the entry file is known; tests invoking resolver helpers in isolation.
Related errors
- Failed to resolve package "${importName}"
- Failed to resolve package "${dep}"
- Failed to resolve global package "${name}"
- Invalid ${type} name "${name}". Only valid npm package names
AI-assisted analysis of slidevjs/slidev@0d798ace58 (2026-08-12).
Data as JSON: /api/errors/b8976a38907a60df.
Report an issue: GitHub.