BloopAI/vibe-kanban · error
Repository already attached to workspace
Error message
Repository already attached to workspace
What it means
This error is produced by map_workspace_manager_error when the workspace manager reports WorkspaceError::RepoAlreadyAttached. It means the repository being added is already associated with the target workspace, so the attach operation is rejected to preserve the one-repo-per-workspace-mapping invariant. It is a domain validation error surfaced as ContainerError::Other via anyhow.
Source
Thrown at crates/local-deployment/src/container.rs:149
container
}
fn map_workspace_manager_error(err: WorkspaceError) -> ContainerError {
match err {
WorkspaceError::Database(err) => ContainerError::Sqlx(err),
WorkspaceError::Worktree(err) => ContainerError::Worktree(err),
WorkspaceError::GitService(err) => ContainerError::GitServiceError(err),
WorkspaceError::Io(err) => ContainerError::Io(err),
WorkspaceError::NoRepositories => {
ContainerError::Other(anyhow!("No repositories provided"))
}
WorkspaceError::Repo(err) => ContainerError::Other(anyhow!(err)),
WorkspaceError::WorkspaceNotFound => {
ContainerError::Other(anyhow!("Workspace not found"))
}
WorkspaceError::RepoAlreadyAttached => {
ContainerError::Other(anyhow!("Repository already attached to workspace"))
}
WorkspaceError::BranchNotFound { repo_name, branch } => ContainerError::Other(anyhow!(
"Branch '{}' does not exist in repository '{}'",
branch,
repo_name
)),
WorkspaceError::PartialCreation(msg) => ContainerError::Other(anyhow!(msg)),
}
}
async fn workspace_repo_inputs(
&self,
workspace_id: Uuid,
) -> Result<(Vec<Repo>, Vec<RepoWorkspaceInput>), ContainerError> {
let workspace_repos =
WorkspaceRepo::find_by_workspace_id(&self.db.pool, workspace_id).await?;
if workspace_repos.is_empty() {
return Err(ContainerError::Other(anyhow!(View on GitHub (pinned to 4deb7eca8f)
Solutions
- Check existing workspace repos (WorkspaceRepo::find_by_workspace_id) before attaching and skip if already present.
- Treat the attach step as idempotent: catch this error and continue instead of failing the whole operation.
- If the repo is attached to the wrong workspace, detach/delete the existing WorkspaceRepo row first, then re-attach.
- Use a transaction/unique constraint so a retried create does not leave a half-created workspace.
Example fix
// before
manager.add_repo_to_workspace(ws_id, repo_id).await?;
// after
if !WorkspaceRepo::find_by_workspace_id(&pool, ws_id).await?
.iter().any(|r| r.repo_id == repo_id) {
manager.add_repo_to_workspace(ws_id, repo_id).await?;
} Defensive patterns
Strategy: validation
Validate before calling
let existing = WorkspaceRepo::find_by_workspace_id(&pool, ws_id).await?;
if existing.iter().any(|r| r.repo_id == repo_id) {
return Ok(()); // already attached, nothing to do
} Try / catch
match container.add_repo_to_workspace(ws_id, repo_id).await {
Err(e) if e.to_string().contains("already attached") => Ok(()), // idempotent
other => other,
} Prevention
- Always list existing workspace repos before attaching a new one.
- Make create/attach calls idempotent on the client (skip if already attached).
- Add a unique constraint on (workspace_id, repo_id) at the DB level.
- Guard UI submit buttons against duplicate requests.
When it happens
Trigger: Calling a workspace-creation or repo-attach API (e.g. container create / add repo to workspace) with a repo_id that already has a WorkspaceRepo row pointing at that workspace_id.
Common situations: Retrying a create request after a partial failure that already persisted the repo attachment; double-submitting a form from the UI; replaying an idempotency-unsafe create call; scripts that add repos to workspaces without checking existing mappings.
Related errors
- result.error
- No repositories provided
- Workspace has no repositories configured
- Failed to list projects (${res.status})
- No setup script configured for this project
AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29).
Data as JSON: /api/errors/dc06a0533aa7c2e9.
Report an issue: GitHub.