odysseus-dev/odysseus · error · Error

result.detail || 'Failed to rename session'

Error message

result.detail || 'Failed to rename session'

What it means

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.

Source

Thrown at static/app.js:1661

          body: JSON.stringify({ name: newName })
        });
        
        const result = await response.json();
        if (response.ok) {
          uiModule.showToast(`Session renamed to ${newName}`);
          renameSessionModal.classList.add('hidden');
          sessionNameInput.value = '';
          // Update the current session name in the UI
          const meta = sessionModule.getSessions().find(s => s.id === sessionModule.getCurrentSessionId());
          if (meta) {
            meta.name = newName;
            const ver = window._appVersion ? ` v${window._appVersion}` : '';
            el('current-meta').textContent = `Session: ${meta.name}${meta.model ? ' ' + meta.model.split('/').pop() : ''}${meta.rag ? ' [RAG]' : ''}${ver}`;
          }
          // Refresh the sessions list
        await sessionModule.loadSessions();
        } else {
          throw new Error(result.detail || 'Failed to rename session');
        }
      } catch (e) {
        uiModule.showError('Failed to rename session: ' + e.message);
      }
    });
  }
  
  if (closeMemoryBtn) {
    closeMemoryBtn.addEventListener('click', () => {
      dismissModal(memoryModal);
    });
  }

  // Sidebar Memory button
  const toolMemoryBtn = el('tool-memory-btn');
  if (toolMemoryBtn && memoryModal) {
    toolMemoryBtn.addEventListener('click', () => {
      memoryModal.classList.remove('hidden');

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. Link the folder that contains SKILL.md (.../tree/<branch>/my-skill), or SKILL.md itself (.../blob/<branch>/my-skill/SKILL.md)
  2. Do not link arbitrary files (README.md, config files) — the importer only understands skill folders and SKILL.md files
  3. If the target is a submodule, link the submodule's real repository URL instead
  4. Check the URL path for typos — a mistyped folder name can resolve to a file of that name in the repo

Example fix

# before
url = "https://github.com/acme/skills/tree/main/skills/debug-helper/README.md"
bundle = fetch_skill_bundle(url)  # 'expected a directory on GitHub'

# after
url = "https://github.com/acme/skills/tree/main/skills/debug-helper"
bundle = fetch_skill_bundle(url)
Defensive patterns

Strategy: validation

Validate before calling

import httpx

def points_at_directory(owner: str, repo: str, ref: str, path: str, token: str | None = None) -> bool:
    """Ask the contents API whether <path> is a directory before importing."""
    url = f"https://api.github.com/repos/{owner}/{repo}/contents/{path}?ref={ref}"
    h = {"Accept": "application/vnd.github+json"}
    if token:
        h["Authorization"] = f"Bearer {token}"
    r = httpx.get(url, headers=h, timeout=30.0)
    return r.status_code == 200 and isinstance(r.json(), list)

Try / catch

try:
    files, src = fetch_skill_bundle(url)
except SkillImportError as e:
    if "expected a directory" in str(e):
        report(f"{url} targets a file — link the folder containing SKILL.md or the SKILL.md blob URL")
        return None
    raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14). Data as JSON: /api/errors/81d3ea56f40d23db. Report an issue: GitHub.