{"record":{"id":"d439fa729a0f1fc5","repo":"deepseek-ai/deepseek-harness","slug":"client-modules-pkgname-declares-dsh-client-but","errorCode":null,"errorMessage":"client-modules: ${pkgName} declares dsh.client but exports no \"./client\" bundle","messagePattern":"client-modules: (.+?) declares dsh\\.client but exports no \"\\./client\" bundle","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/client/modules/src/index.ts","lineNumber":453,"sourceCode":"    } catch {\n      // Not a resolvable package root: loader builtins (cordis:include) and\n      // subpath entries (…/gateway) land here — permanently not a client row.\n      this.pkgMeta.set(pkgName, null)\n      return null\n    }\n    const pkg = JSON.parse(readFileSync(pkgPath, 'utf8')) as Record<string, unknown>\n    const dsh = pkg.dsh\n    const decl = parseDshClient(\n      pkgName,\n      dsh !== null && typeof dsh === 'object' ? (dsh as Record<string, unknown>).client : undefined,\n    )\n    if (decl === undefined || decl.platform !== 'web') {\n      this.pkgMeta.set(pkgName, null)\n      return null\n    }\n    const clientRel = clientExportOf(pkgName, pkg.exports)\n    if (clientRel === undefined) {\n      throw new Error(`client-modules: ${pkgName} declares dsh.client but exports no \"./client\" bundle`)\n    }\n    const meta: PkgMeta = {\n      clientPath: join(dirname(pkgPath), clientRel),\n      ...(decl.inject !== undefined ? { inject: decl.inject } : {}),\n      external: decl.external ?? [],\n      immediately: decl.immediately === true,\n    }\n    this.pkgMeta.set(pkgName, meta)\n    return meta\n  }\n\n  /**\n   * Read the activation-time bundle revision.\n   * @param pkgName - package that declares the client bundle.\n   * @param clientPath - absolute path of the built client artifact.\n   * @returns the bundle content's short hash for use as its revision.\n   * @throws {MissingClientBundleError} when the read fails with `ENOENT`; other filesystem errors are rethrown unchanged.\n   */","sourceCodeStart":435,"sourceCodeEnd":471,"githubUrl":"https://github.com/deepseek-ai/deepseek-harness/blob/b150a551b8d465e31e418e1b2eaf5e79bbb7d28e/packages/client/modules/src/index.ts#L435-L471","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before — package.json\n{ \"exports\": { \".\": \"./lib/index.js\" }, \"dsh\": { \"client\": { \"platform\": \"web\" } } }\n\n// after\n{\n  \"exports\": { \".\": \"./lib/index.js\", \"./client\": \"./lib/client.js\" },\n  \"dsh\": { \"client\": { \"platform\": \"web\" } }\n}","handlingStrategy":"validation","validationCode":"import { readFileSync } from 'node:fs'\nfunction clientExportResolves(pkgDir) {\n  const pkg = JSON.parse(readFileSync(`${pkgDir}/package.json`, 'utf8'))\n  if (pkg.dsh?.client?.platform !== 'web') return true // not a client package\n  const c = pkg.exports?.['./client']\n  return typeof c === 'string' || typeof c?.default === 'string'\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["package-json","manifest","dsh-client","plugin-package"],"backgroundTag":"package-exports-missing","analyzedSha":"b150a551b8d465e31e418e1b2eaf5e79bbb7d28e","analyzedAt":"2026-08-24T18:12:29.105Z","schemaVersion":2},"datasetVersion":"2026-08-24T22:17:12.610Z"}