{"record":{"id":"a6a5ce85fefc791c","repo":"farion1231/cc-switch","slug":"crypto-api-not-available-please-update-your-oper","errorCode":null,"errorMessage":"crypto API not available - please update your operating system","messagePattern":"crypto API not available - please update your operating system","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"src/utils/uuid.ts","lineNumber":20,"sourceCode":" * 生成 UUID v4\n *\n * 优先使用 crypto.randomUUID()，不可用时使用 crypto.getRandomValues() 实现\n *\n * 兼容性：\n * - crypto.randomUUID(): Chrome 92+, Safari 15.4+, Firefox 95+\n * - crypto.getRandomValues(): Chrome 11+, Safari 5+, Firefox 21+\n */\nexport function generateUUID(): string {\n  const cryptoApi = globalThis.crypto;\n\n  // 优先使用原生 API\n  if (typeof cryptoApi?.randomUUID === \"function\") {\n    return cryptoApi.randomUUID();\n  }\n\n  // Fallback: 使用 crypto.getRandomValues 实现 UUID v4\n  if (!cryptoApi?.getRandomValues) {\n    throw new Error(\n      \"crypto API not available - please update your operating system\",\n    );\n  }\n\n  const bytes = new Uint8Array(16);\n  cryptoApi.getRandomValues(bytes);\n\n  // 设置版本 (4) 和变体 (RFC 4122)\n  bytes[6] = (bytes[6] & 0x0f) | 0x40;\n  bytes[8] = (bytes[8] & 0x3f) | 0x80;\n\n  const hex = Array.from(bytes)\n    .map((b) => b.toString(16).padStart(2, \"0\"))\n    .join(\"\");\n\n  return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/farion1231/cc-switch/blob/0b5da510168914b251481654a568c3ffacd62cf4/src/utils/uuid.ts#L2-L38","documentation":"generateUUID prefers crypto.randomUUID() and falls back to a manual v4 built on crypto.getRandomValues; the throw fires only when the Web Crypto API is missing entirely (neither method exists on globalThis.crypto). Browsers expose crypto only in secure contexts, and Node only globals it from v19 — so this is an environment problem, not a logic problem, and it breaks every call site that creates IDs.","triggerScenarios":"Running the app or its unit tests in an insecure context (plain http:// over LAN, not localhost), an old WebView, or Node < 19 / a jsdom environment without a crypto polyfill, then invoking any code path that calls generateUUID (provider/model creation).","commonSituations":"Vitest/jsdom suites failing inside generateUUID; accessing the dev server via LAN IP over http; embedding the web build in an outdated shell.","solutions":["Run tests on Node >= 19, or polyfill in test setup: globalThis.crypto = require('node:crypto').webcrypto","Serve the app from https:// or localhost so the browser/WebView marks the context secure","Provide any getRandomValues polyfill on the host before app code runs"],"exampleFix":"// before (Node < 19 test run)\nconst id = generateUUID(); // throws 'crypto API not available...'\n\n// after (vitest.setup.ts)\nimport { webcrypto } from 'node:crypto';\nif (!globalThis.crypto?.getRandomValues) {\n  Object.defineProperty(globalThis, 'crypto', { value: webcrypto });\n}\nconst id = generateUUID();","handlingStrategy":"fallback","validationCode":"const hasWebCrypto =\n  typeof globalThis.crypto?.randomUUID === 'function' ||\n  typeof globalThis.crypto?.getRandomValues === 'function';\nif (!hasWebCrypto) {\n  // provision a polyfill before any generateUUID call site runs\n}","typeGuard":null,"tryCatchPattern":"try {\n  const id = generateUUID();\n} catch (error) {\n  if (error instanceof Error && error.message.includes('crypto API not available')) {\n    // environment misconfiguration: fix the host (secure context / polyfill), do not swallow\n    throw error;\n  }\n  throw error;\n}","preventionTips":["Run tests on Node >= 19 or set up a crypto polyfill in test setup files","Serve the web app from localhost or https so the context is secure","Add a startup feature check for globalThis.crypto with a clear environmental message"],"tags":["crypto","uuid","environment","secure-context","nodejs"],"backgroundTag":"web-crypto-unavailable","analyzedSha":"0b5da510168914b251481654a568c3ffacd62cf4","analyzedAt":"2026-08-20T14:29:00.113Z","contentChangedAt":"2026-08-20T14:29:00.113Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}