deepseek-ai/deepseek-harness · error
client-modules: ${pkgName} declares dsh.client but exports n
Error message
client-modules: ${pkgName} declares dsh.client but exports no "./client" bundle What it means
resolveMeta() accepts a package as a web client row only if its package.json both declares dsh.client with platform 'web' and exposes a './client' export (a string, or an object whose default is a string). If the declaration exists but exports["./client"] is absent or does not resolve to a string path, the scan throws this error; it surfaces inside the activation aggregate (index 144) or as a steady-state warning. The mismatch is a package-manifest defect: the manifest promises a browser half but never wired its entry.
Source
Thrown at packages/client/modules/src/index.ts:453
} catch {
// Not a resolvable package root: loader builtins (cordis:include) and
// subpath entries (…/gateway) land here — permanently not a client row.
this.pkgMeta.set(pkgName, null)
return null
}
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as Record<string, unknown>
const dsh = pkg.dsh
const decl = parseDshClient(
pkgName,
dsh !== null && typeof dsh === 'object' ? (dsh as Record<string, unknown>).client : undefined,
)
if (decl === undefined || decl.platform !== 'web') {
this.pkgMeta.set(pkgName, null)
return null
}
const clientRel = clientExportOf(pkgName, pkg.exports)
if (clientRel === undefined) {
throw new Error(`client-modules: ${pkgName} declares dsh.client but exports no "./client" bundle`)
}
const meta: PkgMeta = {
clientPath: join(dirname(pkgPath), clientRel),
...(decl.inject !== undefined ? { inject: decl.inject } : {}),
external: decl.external ?? [],
immediately: decl.immediately === true,
}
this.pkgMeta.set(pkgName, meta)
return meta
}
/**
* Read the activation-time bundle revision.
* @param pkgName - package that declares the client bundle.
* @param clientPath - absolute path of the built client artifact.
* @returns the bundle content's short hash for use as its revision.
* @throws {MissingClientBundleError} when the read fails with `ENOENT`; other filesystem errors are rethrown unchanged.
*/View on GitHub (pinned to b150a551b8)
Solutions
- Add the missing export to that package's package.json: "./client": "./lib/client.js" (or { "default": "./lib/client.js" }).
- Build the target so the file exists: `pnpm --filter <pkg> bundle`.
- Run verify-client-packages to catch manifest drift, then restart the server — per-name package metadata is cached and plugin-set changes take effect on restart.
Example fix
// before — package.json
{ "exports": { ".": "./lib/index.js" }, "dsh": { "client": { "platform": "web" } } }
// after
{
"exports": { ".": "./lib/index.js", "./client": "./lib/client.js" },
"dsh": { "client": { "platform": "web" } }
} Defensive patterns
Strategy: validation
Validate before calling
import { readFileSync } from 'node:fs'
function clientExportResolves(pkgDir) {
const pkg = JSON.parse(readFileSync(`${pkgDir}/package.json`, 'utf8'))
if (pkg.dsh?.client?.platform !== 'web') return true // not a client package
const c = pkg.exports?.['./client']
return typeof c === 'string' || typeof c?.default === 'string'
} Prevention
- Follow the new-plugin-package checklist: exports must include '.', './invariant', './client', './src/*', './package.json'.
- Run verify-client-packages in CI so declaration/manifest drift fails before boot.
- Restart after fixing the manifest — per-name package metadata is cached for the process lifetime.
When it happens
Trigger: A Loader entry's package.json contains dsh.client with platform 'web' while its exports map has no "./client" key, or the key is neither a string nor an object with a string default. Typical when the manifest was hand-edited or the new-plugin-package checklist's exports step was skipped.
Common situations: Bringing up a new packages/client/<name> plugin package from a skeleton and forgetting the './client' exports entry; renaming or restructuring exports during a refactor; a JSON merge that silently dropped the key.
Related errors
- client-modules: ${subject} ${field} must be a string array
- ${binName}: profile bundle ${JSON.stringify(packageName)} de
- client-modules: window.__DSH_BOOT__ is missing or not an obj
- client-modules: boot manifest rev must be a string
- ${duplicateMessage}
AI-assisted analysis of deepseek-ai/deepseek-harness@b150a551b8 (2026-08-24).
Data as JSON: /api/errors/d439fa729a0f1fc5.
Report an issue: GitHub.