GitoxideLabs/gitoxide · error

change ID is no longer present in the Tix view

Error message

change ID {change_id} is no longer present in the Tix view

What it means

In `gix-tix`'s reword flow, `relocate_after_editor` maps the change ID recorded before the editor ran back to a commit currently visible in the Tix view. When the mapping walk over commits produces zero matches, the change ID no longer corresponds to any commit that can be relocated onto, so the operation is aborted with this message. This guards against rewriting onto a commit that was concurrently amended, rebased away, or deleted.

Solutions

  1. Re-read the current Tix view (refresh state) and retry the reword against the new commit graph.
  2. Check for concurrent operations (another gix-tix process, an amend) that rewrote the target commit while the editor was open, and re-run after they finish.
  3. Verify the change ID with `crate::change_id::display_short` / inspect recent history to find where the commit went, then re-apply the reword to the correct commit.
  4. If the commit was intentionally dropped, cancel the reword instead of relocating it.

Example fix

// before: assuming the pre-edit change ID is still valid
let (graph, target) = relocate_after_editor(repo, change_id)?;
// after: re-resolve after concurrent rewrites and bail gracefully
match relocate_after_editor(repo, change_id) {
    Ok((graph, target)) => apply(graph, target),
    Err(_) => {
        // refresh view / re-run `gix tix` so change_id maps to the amended commit
        refresh_view(repo)?;
        relocate_after_editor(repo, change_id)
    }
}
Defensive patterns

Strategy: retry

Validate before calling

fn change_id_still_visible(repo: &gix::Repository, change_id: &ChangeId) -> bool {
    crate::change_id::for_commit(repo, head_commit_id(repo)).map(|id| id == *change_id).unwrap_or(false)
}

Try / catch

match relocate_after_editor(repo, change_id) {
    Ok((graph, target)) => proceed(graph, target),
    Err(e) if e.to_string().contains("no longer present") => refresh_view_and_retry(repo, change_id),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `relocate_after_editor` (via `relocates_an_editor_reword_onto_a_concurrent_amend` or `editor_relocation_requires_one_visible_commit` paths) when `crate::change_id::for_commit` never equals the recorded `change_id` for any candidate commit — e.g. the original commit was amended concurrently so its change ID no longer matches, or the commit was dropped/rewritten out of the view.

Common situations: A concurrent `amend` rewrote the commit while the external editor was open; a rebase or history rewrite removed the commit between recording the change ID and applying the reword; a stale Tix view/branch state after another tool rewrote history.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08). Data as JSON: /api/errors/c07438e1352c9c95. Report an issue: GitHub.

Appendix: source

Thrown at gix-tix/src/edit/reword.rs:63

    }
}

pub(crate) fn relocate_after_editor(
    repo: &gix::Repository,
    revisions: &[std::ffi::OsString],
    hidden_revisions: &[std::ffi::OsString],
    change_id: gix::hash::ChangeId,
) -> Result<(crate::history::HistoryGraph, gix::ObjectId)> {
    let graph = super::loaded_view_graph_with_hidden(repo, revisions, hidden_revisions)?;
    let mut matches = Vec::new();
    for id in graph.stored_commit_ids() {
        if crate::change_id::for_commit(repo, id)? == change_id {
            matches.push(id);
        }
    }
    match matches.as_slice() {
        [target] => Ok((graph, *target)),
        [] => anyhow::bail!("change ID {change_id} is no longer present in the Tix view"),
        candidates => {
            let candidates = candidates
                .iter()
                .map(|id| crate::change_id::display_short(repo, *id))
                .collect::<Result<Vec<_>>>()?
                .join("\n  ");
            anyhow::bail!("change ID {change_id} is ambiguous in the Tix view; candidates:\n  {candidates}")
        }
    }
}

#[tracing::instrument(skip_all, fields(commit_id = %id))]
pub(crate) fn document(repo: &gix::Repository, id: gix::ObjectId) -> Result<(gix::command::Prepare, Vec<u8>)> {
    document_with_author(repo, id, None)
}

pub(crate) fn document_with_author(
    repo: &gix::Repository,

View on GitHub (pinned to e73179060b)