{"record":{"id":"67b2942eec3d356f","repo":"stablyai/orca","slug":"preset-name-is-too-long","errorCode":null,"errorMessage":"Preset name is too long.","messagePattern":"Preset name is too long\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"src/main/ipc/repos.ts","lineNumber":2769,"sourceCode":"    // Why: a broadcast failure must never fail the mutation the user actually asked for.\n    console.error('[repos] failed to notify remote clients of repo change', err)\n  }\n  scheduleCurrentWorktreeBaseDirectoryWatcherSync()\n}\n\nfunction notifySparsePresetsChanged(mainWindow: BrowserWindow, repoId: string): void {\n  if (!mainWindow.isDestroyed()) {\n    mainWindow.webContents.send('sparsePresets:changed', { repoId })\n  }\n}\n\nfunction normalizeSparsePresetName(name: string): string {\n  const trimmed = name.trim()\n  if (!trimmed) {\n    throw new Error('Preset name is required.')\n  }\n  if (trimmed.length > 80) {\n    throw new Error('Preset name is too long.')\n  }\n  return trimmed\n}\n\nfunction normalizeSparsePresetDirectories(directories: string[]): string[] {\n  let normalized: string[]\n  try {\n    normalized = normalizeSparseDirectories(directories)\n  } catch (err) {\n    if (\n      err instanceof Error &&\n      err.message === 'Sparse checkout directories must be repo-relative paths.'\n    ) {\n      throw new Error('Preset directories must be repo-relative paths.')\n    }\n    throw err\n  }\n  if (normalized.length === 0) {","sourceCodeStart":2751,"sourceCodeEnd":2787,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/ipc/repos.ts#L2751-L2787","documentation":"Thrown by normalizeSparsePresetName when the trimmed name exceeds 80 characters. This guards storage and UI display width. It runs only after the empty-name check (1289) passes, so the input is guaranteed non-empty.","triggerScenarios":"A user pastes a long descriptive title, or a programmatic flow uses a generated string (e.g. a full path or timestamp list) as the preset name. Any name over 80 chars after trim triggers it.","commonSituations":"Auto-generated names from directory lists; users copying commit messages or filenames as labels; migration importing verbose external names.","solutions":["Enforce maxlength=80 on the name input in the renderer.","Validate name.trim().length <= 80 before the IPC call.","Truncate generated names to <=80 chars with a visible ellipsis policy.","On catch, highlight the input and report the 80-character limit."],"exampleFix":"// before\n<input value={name} onChange={(e) => setName(e.target.value)} />\n\n// after\n<input\n  value={name}\n  maxLength={80}\n  onChange={(e) => setName(e.target.value)}\n/>\n// plus renderer guard:\nif (name.trim().length > 80) { setError('Max 80 characters'); return }","handlingStrategy":"validation","validationCode":"const name = rawName.trim()\nif (name.length > 80) {\n  setError(`Name must be 80 characters or fewer (currently ${name.length})`)\n  return\n}\nawait ipc.invoke('sparsePresets:save', { repoId, name, directories })","typeGuard":"function isValidPresetNameLength(value: unknown): value is string {\n  return typeof value === 'string' && value.trim().length > 0 && value.trim().length <= 80\n}","tryCatchPattern":"try {\n  await ipc.invoke('sparsePresets:save', { repoId, name, directories })\n} catch (e) {\n  if (/too long/i.test((e as Error).message)) setError('Name must be 80 characters or fewer.')\n  else throw e\n}","preventionTips":["Set maxLength={80} on the name input.","Validate trimmed length client-side before save.","Truncate auto-generated names with a clear ellipsis policy."],"tags":["ipc","repos","sparse-checkout","preset","validation","length-limit"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}