{"record":{"id":"da2fddbbaf0e02a3","repo":"can1357/oh-my-pi","slug":"embedded-stats-client-bundle-missing-rebuild-the","errorCode":null,"errorMessage":"Embedded stats client bundle missing. Rebuild the omp binary or npm bundle with embedded stats assets.","messagePattern":"Embedded stats client bundle missing\\. Rebuild the omp binary or npm bundle with embedded stats assets\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/stats/src/server.ts","lineNumber":81,"sourceCode":"\tconst extractRoot = path.resolve(outputDir);\n\n\tfor (const [archivePath, file] of files) {\n\t\tconst sanitizedPath = sanitizeArchivePath(archivePath);\n\t\tif (!sanitizedPath) continue;\n\t\tconst destinationPath = path.resolve(extractRoot, sanitizedPath);\n\t\tif (!destinationPath.startsWith(extractRoot + path.sep)) {\n\t\t\tthrow new Error(`Archive entry escapes extraction directory: ${archivePath}`);\n\t\t}\n\t\tawait Bun.write(destinationPath, file);\n\t}\n}\n\nasync function getEmbeddedClientDir(): Promise<string> {\n\tif (!USE_EMBEDDED_CLIENT) return STATIC_DIR;\n\tif (embeddedClientDirPromise) return embeddedClientDirPromise;\n\n\tif (!EMBEDDED_CLIENT_ARCHIVE) {\n\t\tthrow new Error(\n\t\t\t\"Embedded stats client bundle missing. Rebuild the omp binary or npm bundle with embedded stats assets.\",\n\t\t);\n\t}\n\n\tembeddedClientDirPromise = (async () => {\n\t\tconst bundleHash = Bun.hash(EMBEDDED_CLIENT_ARCHIVE).toString(16);\n\t\tconst outputDir = path.join(EMBEDDED_CLIENT_DIR_ROOT, bundleHash);\n\t\tconst markerPath = path.join(outputDir, \"index.html\");\n\t\ttry {\n\t\t\tconst marker = await fs.stat(markerPath);\n\t\t\tif (marker.isFile()) return outputDir;\n\t\t} catch {}\n\n\t\tawait fs.rm(outputDir, { recursive: true, force: true });\n\t\tawait fs.mkdir(outputDir, { recursive: true });\n\t\tawait extractEmbeddedClientArchive(EMBEDDED_CLIENT_ARCHIVE, outputDir);\n\t\treturn outputDir;\n\t})();","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/stats/src/server.ts#L63-L99","documentation":"When the stats server runs with the embedded client enabled (USE_EMBEDDED_CLIENT), getEmbeddedClientDir() expects the client bundle archive to be baked into the binary/npm bundle at build time. If EMBEDDED_CLIENT_ARCHIVE is absent it throws, instructing the user to rebuild with embedded stats assets — the running artifact was built without the stats client inlined.","triggerScenarios":"staticDir() → getEmbeddedClientDir() on a binary or npm bundle whose build pipeline did not embed the stats client archive (build script skipped the asset-embedding step, or an official artifact was built from a checkout lacking the built client).","commonSituations":"Installing a self-compiled omp built without running the full build (client assets not built first); a stripped-down build configuration; a version mismatch where the build script changed and the embedding step was dropped; running from a source checkout without building the stats client.","solutions":["Rebuild the omp binary or npm bundle with the standard build script so embedded stats assets are included","Build the stats client (packages/stats client build) before the omp bundle step so the archive exists at embed time","Verify the build configuration actually enables client embedding (not a minimal/stripped build)","As a stopgap, serve the client from a static directory instead of the embedded bundle if that mode is available"],"exampleFix":"// before\nbun build ./src/cli.ts --compile --outfile omp   # client assets missing\n// after\nbun run build:stats-client && bun run build:binary  # embeds EMBEDDED_CLIENT_ARCHIVE","handlingStrategy":"validation","validationCode":"import { EMBEDDED_CLIENT_ARCHIVE, USE_EMBEDDED_CLIENT } from './embedded-assets';\nif (USE_EMBEDDED_CLIENT && !EMBEDDED_CLIENT_ARCHIVE) {\n  console.error('This binary was built without embedded stats assets — rebuild with the full build script.');\n}\nconst dir = await getEmbeddedClientDir();","typeGuard":"function hasEmbeddedAssets(a: typeof EMBEDDED_CLIENT_ARCHIVE): a is NonNullable<typeof EMBEDDED_CLIENT_ARCHIVE> {\n  return typeof a === 'string' && a.length > 0;\n}","tryCatchPattern":"try {\n  const dir = await staticDir();\n} catch (err) {\n  if (err.message.includes('Embedded stats client bundle missing')) {\n    console.error('Rebuild: bun run build:stats-client && bun run build (or reinstall an official omp artifact).');\n  } else throw err;\n}","preventionTips":["Always run the stats client build before the omp bundle/compile step","Verify the artifact after build (embedded archive present) before distributing","Prefer official installers/npm bundles over hand-rolled minimal builds","Keep build scripts in sync so the asset-embedding step cannot be silently skipped"],"tags":["build","missing-asset","embedded-bundle","server"],"backgroundTag":"missing-embedded-asset","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}