# Common Issues When Working With Cordis: A Developer’s Guide to Entry Resolution, Configuration, and Runtime Errors

> Resolve common Cordis issues including entry resolution, configuration errors, and runtime problems. This developer's guide helps you overcome Cordis architectural constraints for smoother development.

- Repository: [Cordiverse/cordis](https://github.com/cordiverse/cordis)
- Tags: how-to-guide
- Published: 2026-09-13

---

**The most frequent errors when developing with Cordis involve entry resolution failures in the hierarchical tree, configuration file handling mishaps, service isolation mismatches, and HMR limitations, all of which stem from specific architectural constraints in the loader and core packages.**

Cordis is a meta-framework enabling spatiotemporal composability through a tree of **entries** and a flexible loader system within the `cordiverse/cordis` repository. While its architecture provides powerful plugin isolation and hot-reloading capabilities, developers frequently encounter recurring issues ranging from "cannot resolve entry" crashes to silent configuration failures. Understanding the root causes in the source code—particularly within [`packages/loader/src/config/tree.ts`](https://github.com/cordiverse/cordis/blob/main/packages/loader/src/config/tree.ts) and related modules—allows you to diagnose and prevent these problems systematically.

## Entry Resolution and Hierarchy Errors

The **entry tree** represents plugins as nodes in a colon-separated hierarchy (`EntryTree.sep = ':'`). When this structure is traversed incorrectly, the framework throws specific resolution errors.

### "Cannot Resolve Entry" Errors

When `EntryTree.resolve` walks an ID path and encounters a missing intermediate node, it throws `new Error(\`cannot resolve entry ${id}\`)` at **packages/loader/src/config/tree.ts** lines 75-84. This occurs when:

- An entry ID is malformed or uses incorrect separator syntax
- The parent group was removed but child references remain
- The entry was never created during initialization

To diagnose, examine the stack trace for `EntryTree.resolve` or `EntryTree.resolveGroup`. Verify that the parent group exists and that you are using the correct hierarchical ID format (`parent:child`).

### "Entry Is Not a Group" Errors

After resolving the parent entry, `EntryTree.resolveGroup` expects the entry to possess a `subgroup` property. If absent, it throws `new Error(\`entry ${id} is not a group\`)` at **tree.ts** lines 88-92. This typically happens when you attempt to treat a leaf plugin as a container for sub-plugins.

Ensure the target entry’s `group` flag is set to `true` in its configuration, or verify you are addressing the proper container entry rather than a leaf node.

### Disabled Entry Disposal Not Propagated

When an entry is disabled, the loader marks it and disposes its fiber via `entry.fiber?.dispose()`. However, if the entry’s `parent.tree.store` still holds a reference, further updates may be silently ignored or cause stale state issues.

After disabling an entry, explicitly remove it from its parent group using `group.remove(entry.id)` or trigger a tree refresh to ensure proper cleanup.

## Configuration File Handling Issues

The loader reads configuration files lazily, which creates specific failure modes when files are missing or permissions are restricted.

### Config File Not Found

When a file cannot be opened, the loader propagates `ConfigFileError` with the message `new Error(\`config file not found: ${this.filename}\`)` at **packages/loader/src/index.ts** lines 140-142. This is common when the config path is wrong, the file is deleted, or the process lacks read permissions.

Check the loader’s configuration path via `ctx.loader.config.baseUrl` and confirm the file exists on disk before initialization.

### Read-Only Configuration Warnings

When a configuration file is opened in read-only mode, the loader emits `this.ctx.logger.warn('config file %C is read-only …')` at **index.ts** lines 326-327. This warning signals that runtime changes will remain in memory only and will not persist to disk.

Verify the file’s POSIX permissions or check if the loader was instantiated with the `readOnly` flag set to `true`.

## Runtime Patching and Service Isolation

Cordis uses runtime patches to modify configuration entries and isolation realms to separate service instances. Misconfigurations in these areas generate warnings rather than crashes, making them easy to overlook.

### Patch Application Failures

The `include` package applies runtime patches via `applyPatches`. If a patch target is missing, has a name mismatch, or attempts to insert into a non-group entry, the routine emits `warn('patch insert: entry %C not found', id)` at **packages/include/src/patch.ts** lines 70-74.

Inspect the `patches` array passed to the loader. Ensure each patch’s `id` matches an existing entry and that `insert` operations target only groups, not leaf entries.

### Service Isolation Mismatches

The `isolate` plugin creates per-entry or global realms. When a required service is not implemented, it logs `entry.ctx.logger.warn(new Error(\`expected service ${name} to be implemented\`))` at **packages/loader/src/config/isolate.ts** lines 110-112. This typically occurs when a plugin depends on a service that was never registered via `ctx.provide`.

Review the `isolate` map in the entry’s options and confirm that the dependent service is properly registered in the context before plugin initialization.

## Development Environment and Metadata Issues

Specific errors emerge during development related to hot module replacement and test infrastructure leaking into production.

### HMR Disabled Warnings

The `hmr` package warns when internal loader APIs are unavailable: `this.ctx.logger.warn('loader internals are unavailable, source code HMR is disabled …')` at **packages/hmr/src/index.ts** lines 141-143. This occurs in environments without the `node-addon-require-builtin` package or when the `--expose-internals` flag is omitted.

Enable HMR by passing the necessary CLI flags or installing the required addon to support hot-reloading during development.

### Test Error Leaks and Malformed Metadata

Many test suites deliberately throw `new Error('boom')` or `new Error('test')` to verify error handling paths, such as in **loader/tests/index.spec.ts** line 165 and **timer/tests/index.spec.ts** lines 133-194. If these errors surface in production, they indicate that test code paths were inadvertently shipped.

Additionally, the loader’s built-in plugins are populated from [`package.json`](https://github.com/cordiverse/cordis/blob/main/package.json) metadata. If the `main` field is absent or malformed, imports fail with "cannot resolve entry" errors. Verify the [`package.json`](https://github.com/cordiverse/cordis/blob/main/package.json) in each plugin package points to a valid module.

## Defensive Coding Patterns

Implement these patterns to avoid the issues above:

**Validate entry IDs** using `EntryTree.ensureId` to guarantee uniqueness and correct colon-separated formatting.

**Guard config access** by wrapping loader configuration reads in `try/catch` blocks:

```typescript
import { readFile } from 'node:fs/promises';

async function loadConfig(loader, filename) {
  try {
    const text = await readFile(filename, 'utf8');
    return JSON.parse(text);
  } catch (e) {
    loader.ctx.logger.warn(`config file ${filename} not found, using defaults`);
    return {};
  }
}

```

**Check service availability** before accessing isolated services:

```typescript
function getRealm(entry, name) {
  const symbol = entry.options.isolate?.[name];
  if (!symbol) return null;
  
  const impl = entry.ctx.reflect.store[symbol];
  if (!impl) {
    entry.ctx.logger.warn(`expected service ${name} to be implemented`);
    return null;
  }
  return symbol;
}

```

**Apply patches safely** by passing a custom logger to capture warnings:

```typescript
import { applyPatches } from '@cordisjs/plugin-include';

function safePatch(data, patches, logger) {
  const warn = (msg: string, ...args: any[]) => logger.warn(msg, ...args);
  return applyPatches(data, patches, warn);
}

```

**Enable HMR in development** by spawning Node.js with the required flag:

```typescript
import { spawn } from 'node:child_process';

spawn('node', ['--expose-internals', 'dev.js'], { stdio: 'inherit' });

```

## Summary

- **Validate entry IDs** using `EntryTree.ensureId` before attempting resolution to prevent "cannot resolve entry" errors.
- **Check group status** via the `subgroup` property before treating entries as containers for sub-plugins.
- **Wrap configuration reads** in try/catch blocks to handle `ConfigFileError` gracefully when files are missing or read-only.
- **Verify patch targets** exist and are groups before applying runtime patches via `applyPatches`.
- **Confirm service registration** through `ctx.reflect.store` before accessing isolated services to avoid implementation warnings.
- **Enable development flags** (`--expose-internals`) and install `node-addon-require-builtin` to support HMR functionality.

## Frequently Asked Questions

### Why do I get "cannot resolve entry" errors in Cordis?

This error originates in `EntryTree.resolve` at **packages/loader/src/config/tree.ts** lines 75-84 when the colon-separated ID path contains a missing intermediate node. Verify that parent groups exist before referencing child entries and ensure you are using the correct hierarchical syntax (`parent:child`) rather than flat identifiers.

### How do I fix "entry is not a group" errors?

This occurs in `EntryTree.resolveGroup` at **tree.ts** lines 88-92 when code attempts to access `subgroup` on a leaf entry. Set `group: true` in the entry’s configuration to designate it as a container, or redirect your operation to the correct parent group that holds the target entry.

### Why is HMR disabled in my Cordis development environment?

The HMR package checks for internal loader APIs at **packages/hmr/src/index.ts** lines 141-143. If the `node-addon-require-builtin` package is missing or Node.js was not started with `--expose-internals`, hot reloading is disabled. Install the addon or launch your process with the required flag to enable source code HMR.

### What causes "expected service to be implemented" warnings?

This warning emits from **packages/loader/src/config/isolate.ts** lines 110-112 when a plugin’s isolation realm depends on a service not registered via `ctx.provide`. Ensure all required services are implemented in the context before the plugin initializes, or adjust the `isolate` configuration to remove dependencies on unavailable services.