{"record":{"id":"aef9a0025a0ce7de","repo":"deepseek-ai/deepseek-harness","slug":"binname-profile-bundle-json-stringify-packag","errorCode":null,"errorMessage":"${binName}: profile bundle ${JSON.stringify(packageName)} declares no dsh.bundle in its package.json","messagePattern":"(.+?): profile bundle (.+?) declares no dsh\\.bundle in its package\\.json","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/boot/app-boot/src/profile.ts","lineNumber":393,"sourceCode":"  const dir = resolveProfileDir(name, home)\n  if (!existsSync(join(dir, 'package.json'))) {\n    const template = PROFILE_TEMPLATES[name]\n    if (template === undefined) {\n      throw new Error(\n        `${binName}: profile ${JSON.stringify(name)} does not exist; create it with 'dsh plugin --profile ${name} add <package>'`,\n      )\n    }\n    initProfile(dir, template)\n  }\n  const manifest = normalizeShippedProfile(name, dir, readProfileManifest(binName, dir))\n  // A hand-written profile manifest may omit the dsh section entirely.\n  const bundles = manifest.dsh?.profile?.bundles ?? []\n  const layers = bundles.map((packageName): ProfileLayer => {\n    const packageDir = resolveBundleDir(binName, packageName, installAnchor, dir)\n    const bundleManifest = JSON.parse(readFileSync(join(packageDir, 'package.json'), 'utf8')) as ProfileManifest\n    const declared = bundleManifest.dsh?.bundle?.patch\n    if (declared === undefined) {\n      throw new Error(`${binName}: profile bundle ${JSON.stringify(packageName)} declares no dsh.bundle in its package.json`)\n    }\n    const patchPath = join(packageDir, declared)\n    return { packageName, packageDir, patchPath, patches: loadOverlayPatches(binName, patchPath) }\n  })\n  const patchPath = join(dir, PROFILE_PATCH_FILENAME)\n  const patches = options.userLayer !== false && existsSync(patchPath)\n    ? loadOverlayPatches(binName, patchPath)\n    : []\n  return { name, dir, layers, patchPath, patches }\n}\n\n/**\n * Compose patch layers into the effective entry list over an empty root —\n * the same single `applyEntryPatches` call the boot include makes, so flag\n * derivation and config dumps see exactly what mounts.\n * @param layers - patch lists in application order.\n * @param warn - sink for skipped-patch diagnostics; defaults to silent (boot repeats them).\n * @returns the composed entry list.","sourceCodeStart":375,"sourceCodeEnd":411,"githubUrl":"https://github.com/deepseek-ai/deepseek-harness/blob/b150a551b8d465e31e418e1b2eaf5e79bbb7d28e/packages/boot/app-boot/src/profile.ts#L375-L411","documentation":"Thrown by loadProfile in dsh-app-boot when a package listed under dsh.profile.bundles in the profile's package.json resolves, but the package's own package.json has no dsh.bundle.patch declaration. Every profile layer must be a patch bundle, so a bundle-less package is treated as misconfiguration that fails loud at load instead of being read as 'no patches'. The message names the exact offending package.","triggerScenarios":"Running dsh --profile <name> (or any loadProfile caller) where the profile manifest's dsh.profile.bundles array contains a plain library package, a package whose dsh.bundle section lacks a patch field, or a package version that stopped shipping the manifest.","commonSituations":"Hand-editing a profile's package.json to add a convenience dependency; pointing bundles at a utility package that is not a dsh bundle; upgrading a bundle package that renamed or dropped its dsh.bundle block.","solutions":["Remove the offending package from dsh.profile.bundles in the profile's package.json — only patch bundles belong there","If the package should act as a layer, add a dsh.bundle section with a patch path to its package.json and create that patch file","Open the named package's package.json under node_modules and verify the dsh.bundle spelling and the patch path","Run dsh plugin --profile <name> install so the profile's declared bundle dependencies are actually installed"],"exampleFix":"// before — profile package.json lists a plain package\n\"dsh\": { \"profile\": { \"bundles\": [\"@scope/some-utility\"] } }\n// @scope/some-utility has no dsh.bundle → loadProfile throws\n\n// after — remove it, or make it a bundle:\n\"dsh\": { \"profile\": { \"bundles\": [\"@deepseek-ai/dsh-base\"] } }\n// in @scope/some-utility package.json (if it must patch the profile):\n\"dsh\": { \"bundle\": { \"patch\": \"cordis.patch.yml\" } }","handlingStrategy":"validation","validationCode":"import { readFileSync } from 'node:fs'\n\n// Before booting the profile, verify each listed bundle declares a patch layer.\nfunction assertProfileBundles(profileManifest, resolveDir) {\n  for (const packageName of profileManifest.dsh?.profile?.bundles ?? []) {\n    const pkg = JSON.parse(readFileSync(`${resolveDir(packageName)}/package.json`, 'utf8'))\n    if (typeof pkg.dsh?.bundle?.patch !== 'string') {\n      throw new Error(`${packageName} is not a patch bundle; remove it from dsh.profile.bundles`)\n    }\n  }\n}","typeGuard":"function declaresPatch(pkg) {\n  return typeof pkg?.dsh?.bundle?.patch === 'string' && pkg.dsh.bundle.patch.length > 0\n}","tryCatchPattern":null,"preventionTips":["Only list packages that ship a dsh.bundle.patch declaration in dsh.profile.bundles","Add layers through dsh plugin --profile <name> add <package> instead of hand-editing the manifest","After upgrading a bundle, check its package.json still carries dsh.bundle before booting the profile"],"tags":["config","plugin","profile","package-json","bootstrap"],"backgroundTag":"invalid-package-manifest","analyzedSha":"b150a551b8d465e31e418e1b2eaf5e79bbb7d28e","analyzedAt":"2026-08-24T18:12:29.105Z","schemaVersion":2},"datasetVersion":"2026-08-24T22:17:12.610Z"}