semaphoreui/semaphore · error
duplicate key
Error message
duplicate key %s
What it means
ValueMap.appendValuesAndCheck detects duplicate entity keys when checkDuplicates is enabled. Two objects of the same type sharing the same scope+DbKey indicate corrupt or overlapping export data, so appending is aborted.
Solutions
- Deduplicate the values slice before appending (key by scope+GetDbKey)
- Verify the source store does not contain duplicate rows for the entity's DB key
- Reset or recreate the ValueMap if a prior load already inserted the same entities
Example fix
// before
chain.appendValues(values) // errors on second occurrence of key
// after
seen := map[EntityKey]bool{}
for _, v := range values {
if !seen[v.GetDbKey()] {
seen[v.GetDbKey()] = true
chain.appendValues([]T{v})
}
} Defensive patterns
Strategy: try-catch
Validate before calling
seen := map[string]bool{}
for _, v := range values {
k := scope + v.GetDbKey()
if seen[k] { return fmt.Errorf("pre-check: duplicate %s", k) }
seen[k] = true
} Try / catch
err := valueMap.appendValues(values)
if err != nil {
var dup string
if n, _ := fmt.Sscanf(err.Error(), "duplicate key %s", &dup); n == 1 {
log.Warnf("skipping duplicate %s", dup)
return nil
}
return err
} Prevention
- Deduplicate query results before loading into the ValueMap
- Never load the same export source twice into one chain
- Enforce unique DB keys at the source schema level
When it happens
Trigger: Calling appendValues (which uses appendValuesAndCheck with duplicate checking) with a batch containing two EntityObject values whose GetDbKey() is identical within the same scope — e.g. loading the same entity twice or a store query returning duplicates.
Common situations: Database rows with duplicated logical keys; loading the same export file or entity set twice into one chain; buggy custom exporter emitting the same object multiple times.
Related errors
AI-assisted analysis of semaphoreui/semaphore@1774ccb71a (2026-09-07).
Data as JSON: /api/errors/dd79f1a922a3434b.
Report an issue: GitHub.
Appendix: source
Thrown at services/export/Exporter.go:258
}
}
return keys, nil
}
func (t *ValueMap[T]) appendValues(values []T, scope string) error {
return t.appendValuesAndCheck(values, scope, t.uniqueKeys)
}
func (t *ValueMap[T]) appendValuesAndCheck(values []T, scope string, checkDuplicates bool) error {
if t.values == nil {
t.keyScopeMap = make(map[string]bool)
t.values = make([]EntityObject[T], 0)
}
for _, v := range values {
if checkDuplicates {
_, ok := t.keyScopeMap[scope+v.GetDbKey()]
if ok {
return fmt.Errorf("duplicate key %s", v.GetDbKey())
}
t.keyScopeMap[scope+v.GetDbKey()] = true
}
t.values = append(t.values, EntityObject[T]{value: v, scope: scope})
}
return nil
}
func (t *ValueMap[T]) exportDependsOn() []string {
return []string{}
}
func (t *ValueMap[T]) importDependsOn() []string {
return []string{}
}
func (t *ValueMap[T]) onError(err string) {
if t.errs == nil {View on GitHub (pinned to 1774ccb71a)