dagger/dagger · error

received uncommitted patch before metadata

Error message

received uncommitted patch before metadata

What it means

PackGitUncommitted expects a gRPC stream where the first message is always the Metadata message and subsequent messages are patch Chunks. If a Chunk arrives before any Metadata message, the client cannot know the HEAD SHA or nested repositories and aborts with this protocol-violation error. It indicates the server sent messages out of order or a non-conforming stream.

Source

Thrown at engine/engineutil/client.go:764

				return nil, fmt.Errorf("received more than one uncommitted metadata message")
			}
			if errInfo := msg.Metadata.GetError(); errInfo != nil {
				switch errInfo.Type {
				case git.NOT_A_REPO:
					return nil, fmt.Errorf("%s: %w", errInfo.Message, gitutil.ErrGitNoRepo)
				case git.NOT_FOUND, git.UNCOMMITTED_UNSUPPORTED:
					return nil, fmt.Errorf("%s: %w", errInfo.Message, ErrGitUncommittedUnsupported)
				default:
					return nil, errors.New(errInfo.Message)
				}
			}
			pack = &GitUncommittedPack{
				HeadSHA:            msg.Metadata.HeadSha,
				NestedRepositories: append([]string(nil), msg.Metadata.NestedRepositories...),
			}
		case *git.PackUncommittedResponse_Chunk:
			if pack == nil {
				return nil, fmt.Errorf("received uncommitted patch before metadata")
			}
			if spool == nil {
				spool, err = newGitPackSpool("dagger-uncommitted-pack-*", git.MaxGitPackBytes)
				if err != nil {
					return nil, fmt.Errorf("create uncommitted pack spool: %w", err)
				}
			}
			if err := spool.write(msg.Chunk); err != nil {
				return nil, fmt.Errorf("receive uncommitted pack: %w", err)
			}
		}
	}
	if pack == nil {
		return nil, fmt.Errorf("missing uncommitted pack metadata message")
	}
	if pack.HeadSHA != expectedHeadSHA {
		return nil, fmt.Errorf("uncommitted pack HEAD %s does not match expected %s", pack.HeadSHA, expectedHeadSHA)
	}

View on GitHub (pinned to 82ba2681db)

Solutions

  1. Ensure engine and dagger CLI/SDK versions match (dagger engine upgrade in lockstep)
  2. Retry the operation once — transient stream corruption is rare but possible
  3. Fall back to directory-sync-based loading if available, since PackGitUncommitted is an optimization
  4. File a bug with engine logs if reproducible; this is a server-side protocol violation
Defensive patterns

Strategy: retry

Try / catch

var pack *GitUncommittedPack
var err error
for i := 0; i < 2; i++ {
	pack, err = client.PackGitUncommitted(ctx, path, sha)
	if err == nil || !strings.Contains(err.Error(), "before metadata") {
		break
	}
	time.Sleep(time.Second) // protocol violation may be transient stream corruption
}

Prevention

When it happens

Trigger: The server-side git service streams a PackUncommittedResponse_Chunk as the first message instead of PackUncommittedResponse_Metadata — typically a bug or version mismatch in the engine's git streaming implementation.

Common situations: Engine/client version skew where the message ordering contract changed; a custom or patched engine emitting chunks first; race or corruption in the gRPC stream delivery.

Related errors


AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05). Data as JSON: /api/errors/66726f4dc9370565. Report an issue: GitHub.