semaphoreui/semaphore · error

key not found

Error message

%s key %s not found

What it means

TypeKeyMapper.getNewKey looks up the replacement key for an entity being imported/exported in the map Keys[name][scope][oldKey]. When no mapping exists for the given type name, scope, and old key, it fails so the export/import can silently skip or mis-reference an entity.

Solutions

  1. Re-generate the export file from the same (or compatible) source instance/version as the target
  2. Ensure all entities of the given type are loaded and registered in the TypeKeyMapper (via mapKeys) before resolving dependent keys
  3. Check that the scope string matches exactly between where keys were mapped and where getNewKey is called

Example fix

// before
newKey, err := mapper.getNewKey("project", scope, oldKey) // panics into error when missing
// after
if _, ok := mapper.Keys["project"][scope][oldKey]; !ok {
    log.Warnf("skipping unmapped project key %s", oldKey)
    return nil
}
Defensive patterns

Strategy: try-catch

Validate before calling

if _, ok := mapper.Keys[name][scope][oldKey]; !ok {
    // handle missing mapping before calling getNewKey
}

Try / catch

newKey, err := mapper.getNewKey(name, scope, oldKey)
if err != nil {
    if strings.HasSuffix(err.Error(), "not found") {
        // skip entity or create a fresh mapping via mapKeys
        return nil
    }
    return err
}

Prevention

When it happens

Trigger: During export/import key remapping, getNewKey (called by getNewKeyInt/getNewKeyIntRef) is asked for a mapping of an old EntityKey that was never registered via mapKeys for that entity type and scope — e.g. the source export references an object the target store never loaded, or IDs shifted between versions.

Common situations: Importing an export file produced by a different Semaphore version or different instance where referenced entity IDs (project, template, inventory keys) do not exist in the destination; stale or partially-loaded export data.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


AI-assisted analysis of semaphoreui/semaphore@1774ccb71a (2026-09-07). Data as JSON: /api/errors/f2f998a4802fc032. Report an issue: GitHub.

Appendix: source

Thrown at services/export/Exporter.go:154

			errHandler.onError(err.Error())
			return nil, nil
		}
		return nil, err
	}

	newKey, err := strconv.Atoi(key)
	if err != nil {
		return nil, err
	}

	return &newKey, nil
}

func (d *TypeKeyMapper) getNewKey(name string, scope string, oldKey EntityKey) (EntityKey, error) {
	newKey, ok := d.Keys[name][scope][oldKey]
	if !ok {
		msg := fmt.Sprintf("%s key %s not found", name, oldKey)
		return "", errors.New(msg)
	}

	return newKey, nil
}

func (d *TypeKeyMapper) mapKeys(name string, scope string, oldKey EntityKey, newKey EntityKey) error {
	_, ok := d.Keys[name]
	if !ok {
		d.Keys[name] = make(map[string]map[EntityKey]EntityKey)
	}

	_, ok = d.Keys[name][scope]
	if !ok {
		d.Keys[name][scope] = make(map[EntityKey]EntityKey)
	}

	d.Keys[name][scope][oldKey] = newKey
	return nil

View on GitHub (pinned to 1774ccb71a)