{"record":{"id":"c3e8a3b1b1a46e08","repo":"odysseus-dev/odysseus","slug":"data-error-failed-to-generate-ssh-key","errorCode":null,"errorMessage":"data.error || 'Failed to generate SSH key'","messagePattern":"data\\.error \\|\\| 'Failed to generate SSH key'","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"static/js/cookbook-hwfit.js","lineNumber":2401,"sourceCode":"    const pf = port && port !== '22' ? `-p ${port} ` : '';\n    const remote = [\n      `KEY=${_singleQuote(publicKey)}`,\n      'mkdir -p ~/.ssh',\n      'chmod 700 ~/.ssh',\n      'touch ~/.ssh/authorized_keys',\n      '(grep -qxF \"$KEY\" ~/.ssh/authorized_keys || printf \"%s\\\\n\" \"$KEY\" >> ~/.ssh/authorized_keys)',\n      'chmod 600 ~/.ssh/authorized_keys',\n    ].join(' && ');\n    return `ssh -o StrictHostKeyChecking=accept-new ${pf}${host} ${_singleQuote(remote)}`;\n  }\n\n  async function _fetchCookbookSshKey(generate = false) {\n    const res = await fetch('/api/cookbook/ssh-key', {\n      method: generate ? 'POST' : 'GET',\n      credentials: 'same-origin',\n    });\n    const data = await res.json();\n    if (generate && !data.ok) throw new Error(data.error || 'Failed to generate SSH key');\n    return (data.public_key || '').trim();\n  }\n\n  async function _populateServerKeyPanel(entry, generate = false) {\n    const panel = entry.querySelector('.cookbook-server-key-panel');\n    const cmdBox = entry.querySelector('.cookbook-server-key-command');\n    const copyBtn = entry.querySelector('.cookbook-server-key-copy');\n    const genBtn = entry.querySelector('.cookbook-server-key-gen');\n    if (!panel || !cmdBox) return;\n    const host = entry.querySelector('.cookbook-srv-host')?.value?.trim() || '';\n    const port = entry.querySelector('.cookbook-srv-port')?.value?.trim() || '';\n    if (!host || !host.includes('@')) {\n      cmdBox.value = 'Enter the server as user@host first.';\n      if (copyBtn) copyBtn.disabled = true;\n      return;\n    }\n    if (!/^[A-Za-z0-9._~-]+@[A-Za-z0-9._:-]+$/.test(host) || (port && !/^\\d{1,5}$/.test(port))) {\n      cmdBox.value = 'Use a plain SSH target like user@host and an optional numeric port.';","sourceCodeStart":2383,"sourceCodeEnd":2419,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/static/js/cookbook-hwfit.js#L2383-L2419","documentation":"Error thrown when POST /api/cookbook/ssh-key (generate=true) answers with a body where ok is falsy — the endpoint responded, but reported it could not generate/retrieve the local SSH keypair. The message is data.error or a generic fallback.","triggerScenarios":"POST /api/cookbook/ssh-key returns 200 with {ok:false,error:'ssh-keygen failed...'} because ssh-keygen is missing, the ~/.ssh directory is unwritable, a key exists but is unreadable, or disk/permission issues prevent writing the key file.","commonSituations":"Server runs as a user without a writable HOME; ssh-keygen not installed in the container/image; ~/.ssh owned by root after a manual edit; read-only filesystem in a container.","solutions":["Run ssh-keygen -t ed25519 manually as the server user to reproduce the underlying failure","Check permissions: mkdir -p ~/.ssh && chmod 700 ~/.ssh, ensure ownership by the server user","Install openssh-client if ssh-keygen is absent","Read data.error in the thrown message — it usually contains the ssh-keygen stderr"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const res = await fetch('/api/cookbook/ssh-key', { method: generate ? 'POST' : 'GET', credentials: 'same-origin' });\n  const data = await res.json();\n  if (generate && !data.ok) throw new Error(data.error || 'Failed to generate SSH key');\n  return (data.public_key || '').trim();\n} catch (e) {\n  showKeyPanelError(`SSH key ${generate ? 'generation' : 'load'} failed: ${e.message}`);\n  return '';\n}","preventionTips":["Pre-install openssh-client in the server image so generation never fails for missing binary","Ensure ~/.ssh is writable by the server user (700) as part of setup","Surface data.error verbatim — it contains ssh-keygen stderr needed for diagnosis"],"tags":["fetch","ssh","key-generation","cookbook","permissions"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}