kopia/kopia · error
ACL entry for a given user and target already exists
Error message
ACL entry for a given user and target already exists %v: %v
What it means
AddACL found an existing entry with the same user and target, and the requested entry's access level is lower than the existing one while overwrite=false. To avoid silently downgrading permissions, the operation is refused. Set overwrite=true to replace the entry regardless.
Solutions
- Pass overwrite=true to AddACL (or the appropriate CLI flag) to replace the existing entry
- Remove the existing ACL entry first, then add the new one
- Choose an equal or higher access level if the downgrade was unintentional
Example fix
// before AddACL(ctx, rep, entry, false) // after AddACL(ctx, rep, entry, true)
Defensive patterns
Strategy: validation
Validate before calling
entries, _ := acl.LoadEntries(ctx, rep, nil)
for _, e := range entries {
if e.User == newUser && maps.Equal(e.Target, newTarget) && newEntry.Access < e.Access {
return fmt.Errorf("would downgrade %s; pass overwrite=true intentionally", newUser)
}
} Prevention
- List existing ACLs with 'kopia acl list' before adding entries
- Make overwrite an explicit, audited decision in automation
- Detect duplicate (user, target) pairs in provisioning scripts
When it happens
Trigger: Calling AddACL without overwrite for a (User, Target) pair that already exists with a higher access level, e.g. adding a 'read' ACL for a user who already has 'write' on the same target.
Common situations: Re-running an ACL provisioning script after permissions were raised; assuming AddACL upserts by default; conflicting ACLs created by two administrators.
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- error deleting old
- error listing ACL manifests
- error loading ACL manifest
- error validating ACL
- error writing manifest
AI-assisted analysis of kopia/kopia@82495e54b5 (2026-09-07).
Data as JSON: /api/errors/79c1a27a96c4332a.
Report an issue: GitHub.
Appendix: source
Thrown at internal/acl/acl_manager.go:126
return result, nil
}
// AddACL validates and adds the specified ACL entry to the repository.
func AddACL(ctx context.Context, w repo.RepositoryWriter, e *Entry, overwrite bool) error {
if err := e.Validate(); err != nil {
return errors.Wrap(err, "error validating ACL")
}
entries, err := LoadEntries(ctx, w, nil)
if err != nil {
return errors.Wrap(err, "unable to load ACL entries")
}
for _, oldE := range entries {
if e.User == oldE.User && maps.Equal(e.Target, oldE.Target) {
if !overwrite && e.Access < oldE.Access {
return errors.Errorf("ACL entry for a given user and target already exists %v: %v", oldE.User, oldE.Target)
}
if err = w.DeleteManifest(ctx, oldE.ManifestID); err != nil {
return errors.Wrap(err, "error deleting old")
}
}
}
manifestID, err := w.PutManifest(ctx, map[string]string{
manifest.TypeLabelKey: aclManifestType,
}, e)
if err != nil {
return errors.Wrap(err, "error writing manifest")
}
e.ManifestID = manifestID
return nilView on GitHub (pinned to 82495e54b5)