{"record":{"id":"81d3ea56f40d23db","repo":"odysseus-dev/odysseus","slug":"result-detail-failed-to-rename-session","errorCode":null,"errorMessage":"result.detail || 'Failed to rename session'","messagePattern":"result\\.detail \\|\\| 'Failed to rename session'","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"static/app.js","lineNumber":1661,"sourceCode":"          body: JSON.stringify({ name: newName })\n        });\n        \n        const result = await response.json();\n        if (response.ok) {\n          uiModule.showToast(`Session renamed to ${newName}`);\n          renameSessionModal.classList.add('hidden');\n          sessionNameInput.value = '';\n          // Update the current session name in the UI\n          const meta = sessionModule.getSessions().find(s => s.id === sessionModule.getCurrentSessionId());\n          if (meta) {\n            meta.name = newName;\n            const ver = window._appVersion ? ` v${window._appVersion}` : '';\n            el('current-meta').textContent = `Session: ${meta.name}${meta.model ? ' ' + meta.model.split('/').pop() : ''}${meta.rag ? ' [RAG]' : ''}${ver}`;\n          }\n          // Refresh the sessions list\n        await sessionModule.loadSessions();\n        } else {\n          throw new Error(result.detail || 'Failed to rename session');\n        }\n      } catch (e) {\n        uiModule.showError('Failed to rename session: ' + e.message);\n      }\n    });\n  }\n  \n  if (closeMemoryBtn) {\n    closeMemoryBtn.addEventListener('click', () => {\n      dismissModal(memoryModal);\n    });\n  }\n\n  // Sidebar Memory button\n  const toolMemoryBtn = el('tool-memory-btn');\n  if (toolMemoryBtn && memoryModal) {\n    toolMemoryBtn.addEventListener('click', () => {\n      memoryModal.classList.remove('hidden');","sourceCodeStart":1643,"sourceCodeEnd":1679,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/static/app.js#L1643-L1679","documentation":"Raised by _list_github_dir when the GitHub contents API response body is not a JSON array. The endpoint https://api.github.com/repos/<o>/<r>/contents/<path>?ref=<ref> returns a single object (dict) when <path> resolves to a file, and an array when it resolves to a directory — so this error means the traversal reached something that is not a directory listing.","triggerScenarios":"The URL path targets a file whose name does not end in skill.md (fetch_skill_bundle only short-circuits the file case for *.skill.md, everything else goes into _list_github_dir), or the API returns an unexpected object shape (error payload with 200, or a submodule/symlink entry resolved as an object). A repo root that is empty of directories can also return []-vs-object edge shapes on unusual refs.","commonSituations":"User pastes a /tree/<branch>/path/to/readme.md or /blob/... URL for a non-SKILL.md file; a ref that points at a tag whose tree layout confuses the caller; linking a path that is actually a submodule.","solutions":["Link the folder that contains SKILL.md (.../tree/<branch>/my-skill), or SKILL.md itself (.../blob/<branch>/my-skill/SKILL.md)","Do not link arbitrary files (README.md, config files) — the importer only understands skill folders and SKILL.md files","If the target is a submodule, link the submodule's real repository URL instead","Check the URL path for typos — a mistyped folder name can resolve to a file of that name in the repo"],"exampleFix":"# before\nurl = \"https://github.com/acme/skills/tree/main/skills/debug-helper/README.md\"\nbundle = fetch_skill_bundle(url)  # 'expected a directory on GitHub'\n\n# after\nurl = \"https://github.com/acme/skills/tree/main/skills/debug-helper\"\nbundle = fetch_skill_bundle(url)","handlingStrategy":"validation","validationCode":"import httpx\n\ndef points_at_directory(owner: str, repo: str, ref: str, path: str, token: str | None = None) -> bool:\n    \"\"\"Ask the contents API whether <path> is a directory before importing.\"\"\"\n    url = f\"https://api.github.com/repos/{owner}/{repo}/contents/{path}?ref={ref}\"\n    h = {\"Accept\": \"application/vnd.github+json\"}\n    if token:\n        h[\"Authorization\"] = f\"Bearer {token}\"\n    r = httpx.get(url, headers=h, timeout=30.0)\n    return r.status_code == 200 and isinstance(r.json(), list)","typeGuard":null,"tryCatchPattern":"try:\n    files, src = fetch_skill_bundle(url)\nexcept SkillImportError as e:\n    if \"expected a directory\" in str(e):\n        report(f\"{url} targets a file — link the folder containing SKILL.md or the SKILL.md blob URL\")\n        return None\n    raise","preventionTips":["Only link folders that contain SKILL.md, or SKILL.md blob URLs","Pre-flight the URL with the contents API to confirm it returns a list","Reject URLs whose last segment has a file extension other than skill.md in your own UI"],"tags":["github-api","validation","skill-import","url-parsing"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}