{"record":{"id":"e0868b4f636888a7","repo":"tinyhumansai/openhuman","slug":"not-running-in-tauri-e0868b","errorCode":null,"errorMessage":"Not running in Tauri","messagePattern":"Not running in Tauri","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"app/src/utils/tauriCommands/cron.ts","lineNumber":76,"sourceCode":"  name?: string;\n  schedule: CoreCronSchedule;\n  job_type?: 'shell' | 'agent';\n  command?: string;\n  prompt?: string;\n  session_target?: 'isolated' | 'main';\n  model?: string;\n  agent_id?: string;\n  /** Agent profile to attribute this job to (snake_case on the wire). Omit for none. */\n  profile_id?: string;\n  delivery?: { mode: string; channel?: string | null; to?: string | null; best_effort?: boolean };\n  delete_after_run?: boolean;\n}\n\nexport async function openhumanCronAdd(\n  params: CronAddParams\n): Promise<CommandResponse<CoreCronJob>> {\n  if (!isTauri()) {\n    throw new Error('Not running in Tauri');\n  }\n  return await callCoreRpc<CommandResponse<CoreCronJob>>({ method: 'openhuman.cron_add', params });\n}\n\nexport async function openhumanCronList(): Promise<CommandResponse<CoreCronJob[]>> {\n  if (!isTauri()) {\n    throw new Error('Not running in Tauri');\n  }\n  return await callCoreRpc<CommandResponse<CoreCronJob[]>>({ method: 'openhuman.cron_list' });\n}\n\nexport async function openhumanCronUpdate(\n  jobId: string,\n  patch: Record<string, unknown>\n): Promise<CommandResponse<CoreCronJob>> {\n  if (!isTauri()) {\n    throw new Error('Not running in Tauri');\n  }","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/app/src/utils/tauriCommands/cron.ts#L58-L94","documentation":"openhumanCronAdd creates a scheduled job (name/schedule/prompt plus optional model, agent_id, profile_id, delivery mode, delete_after_run) via the openhuman.cron_add core RPC over the Tauri bridge. The guard rejects when the strict isTauri() is false — no shell means no embedded core and no scheduler to accept the job. The strict check also returns false during the CEF bootstrap gap.","triggerScenarios":"Saving a new automation from /settings/automations (the old /routines, /workflows routes redirect there) while under `pnpm dev`; creating a job in a Vitest test without mocks; the save racing bridge wiring at startup.","commonSituations":"Building automation-creation UI in browser mode; delivery-mode or profile_id forms tested outside the shell where every submit rejects.","solutions":["Test cron creation under `pnpm dev:app` so the scheduler persists the job.","Gate the submit handler on isTauri() and disable form submission in browser mode.","Catch the rejection, match 'Not running in Tauri', and keep the draft without pretending it saved.","Mock the cron wrapper module in form tests."],"exampleFix":"// before\nconst { result: job } = await openhumanCronAdd(params);\n\n// after\nif (!isTauri()) {\n  toast('Automations run inside the desktop app');\n  return;\n}\nconst { result: job } = await openhumanCronAdd(params);","handlingStrategy":"validation","validationCode":"if (!isTauri()) {\n  toast('Automations run inside the desktop app');\n  return;\n}\nconst { result: job } = await openhumanCronAdd(params);","typeGuard":"function isNotRunningInTauriError(err: unknown): boolean {\n  return err instanceof Error && err.message === 'Not running in Tauri';\n}","tryCatchPattern":"try {\n  return await openhumanCronAdd(params);\n} catch (err) {\n  if (err instanceof Error && err.message === 'Not running in Tauri') {\n    return null; // keep the draft, do not report creation\n  }\n  throw err;\n}","preventionTips":["Disable the create/submit control outside the shell.","Validate schedule fields before calling so environment and validation errors stay distinguishable.","Test job creation under `pnpm dev:app`."],"tags":["tauri","ipc","environment-guard","cron","automation","mutation"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}