gitbutlerapp/gitbutler · error

not yet implemented

Error message

not yet implemented

What it means

but-core's snapshot::create_stash_commit is a declared-but-unimplemented API: the body is todo!(), which panics with 'not yet implemented' when called. Its purpose is to create (or restack) the stash reference commit carrying CommitMetadata on top of an existing stash for the given reference.

Solutions

  1. Do not call create_stash_commit until it is implemented; check for alternative snapshot APIs in but-core.
  2. Implement the function: build a stash commit on top of the existing stash ref (or create the ref) using _snapshot_tree and _metadata, matching the documented semantics.
  3. If you own the calling code, gate the call behind a capability check or feature flag and return a proper error instead of panicking.
  4. Convert todo!() to a typed anyhow::bail!("stash commit creation is not implemented") so callers get a recoverable error.
  5. Add a test that pins the expected behavior once implemented.

Example fix

// before
) -> anyhow::Result<Commit<'repo>> {
    todo!()
}
// after
) -> anyhow::Result<Commit<'repo>> {
    anyhow::bail!("create_stash_commit is not yet implemented")
}
Defensive patterns

Strategy: try-catch

Validate before calling

// treat the stub as unavailable until implemented
fn stash_create_available() -> bool { false }
if !stash_create_available() { return Err(StashUnavailable); }

Type guard

// Rust: capability probe instead of a type guard
fn supports_stash_commit() -> bool {
  // probe or version check; todo!() stubs have no safe probe today
  false
}

Try / catch

// today todo!() PANICS, so catch_unwind is required if you must call it
let result = std::panic::catch_unwind(|| {
  Snapshot::create_stash_commit(tree, ref_name, metadata)
});
match result {
  Ok(Ok(commit)) => apply(commit),
  _ => fallback_snapshot_path()?,
}

Prevention

When it happens

Trigger: Any call to Snapshot::create_stash_commit in the current code — the function is a stub, so the first invocation panics unconditionally.

Common situations: Worktree snapshot/save flows that route through the stash API before the implementation landed; tests or CLI commands exercising stash creation; callers assuming the public API is complete because it compiles and is documented.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@58e5313667 (2026-09-18). Data as JSON: /api/errors/7eab7a6abe4bd1dd. Report an issue: GitHub.

Appendix: source

Thrown at crates/but-core/src/snapshot/mod.rs:85

    /// Metadata attached to [`Commit`]s holding snapshots.
    pub struct CommitMetadata {
        /// The name of the operation that created the commit.
        /// This is an internal string.
        pub operation: String,
        /// The title of the commit for user consumption, typically created using information from `trailers`.
        pub title: String,
        /// Properties to be stored with the commit.
        pub trailers: Vec<CommitTrailer>,
    }

    /// Given a `snapshot_tree` as created by [`super::create_tree()`], associate it with the stash of `ref_name`.
    /// If a stash already exists, put it on top, with a new commit to carry `metadata`.
    pub fn create_stash_commit<'repo>(
        _snapshot_tree: gix::Id<'repo>,
        _ref_name: &gix::refs::FullNameRef,
        _metadata: CommitMetadata,
    ) -> anyhow::Result<Commit<'repo>> {
        todo!()
    }

    /// List all stash commits available for `ref_name`, with the top-most (most recent) first, and the oldest one last.
    pub fn list_stash_commits<'repo>(
        _repo: &'repo gix::Repository,
        _ref_name: &gix::refs::FullNameRef,
    ) -> anyhow::Result<Vec<Commit<'repo>>> {
        todo!()
    }

    /// List all references for which a stash is available.
    /// Note that these might not actually exist in the `repo`, for instance if the actual reference was renamed.
    pub fn list_stash_references(_repo: &gix::Repository) -> Vec<gix::refs::FullName> {
        todo!()
    }

    /// Remove the top-most stash from the top of `ref_name` and write back all changes.
    /// Just like Git, write merge conflicts and update the index, possibly update refs and metadata.

View on GitHub (pinned to 58e5313667)