t8y2/dbx · error

ETCD_NOT_FOUND

ETCD_NOT_FOUND

Error message

ETCD_NOT_FOUND: source key does not exist

What it means

rename first GETs the source key to read its value and metadata. If etcd responds 100 Key not found, the driver refuses to proceed with this error, since there is nothing to rename. The rename is not performed.

Source

Thrown at agents/drivers/etcd2-go/kv.go:309

	sourceKey, err := keyBytesParam(params)
	if err != nil {
		return nil, err
	}
	newKey := stringOrNull(params, "newKey")
	if newKey == nil || *newKey == "" {
		return nil, errors.New("ETCD_NEWKEY_REQUIRED")
	}
	targetKey := *newKey
	if sourceKey == targetKey {
		return map[string]any{"renamed": true, "revision": nil}, nil
	}

	ctx, cancel := s.beginOperation()
	defer s.endOperation(cancel)
	body, _, err := client.do(ctx, http.MethodGet, v2KeyPath(sourceKey), "", nil)
	if err != nil {
		if isNotFound(err) {
			return nil, errors.New("ETCD_NOT_FOUND: source key does not exist")
		}
		return nil, err
	}
	var source v2KeysResponse
	if err := json.Unmarshal(body, &source); err != nil {
		return nil, err
	}
	if source.Node == nil || source.Node.Dir {
		return nil, errors.New("ETCD_NOT_FOUND: source key does not exist")
	}
	if _, _, err := client.do(ctx, http.MethodGet, v2KeyPath(targetKey), "", nil); err == nil {
		return nil, errors.New("ETCD_CAS_CONFLICT: source changed or target already exists")
	} else if !isNotFound(err) {
		return nil, err
	}

	expected := longOrNull(params, "expectedModRevision")
	expectedRevision := source.Node.ModifiedIndex

View on GitHub (pinned to c0390bff16)

Solutions

  1. GET the source key first to confirm it exists before renaming.
  2. Check the key spelling, leading '/', and any prefix/namespace used by other tools writing this key.
  3. If a concurrent process may have renamed it already, treat this as success (idempotent rename).
  4. Verify you are connected to the expected etcd endpoint/cluster.

Example fix

// before
res, err := agent.Handle(ctx, "rename", map[string]any{"key": "cfg/old", "newKey": "cfg/new"})
// after
if _, err := agent.Handle(ctx, "get", map[string]any{"key": "cfg/old"}); err != nil {
    return fmt.Errorf("source missing, skip rename: %w", err)
}
res, err := agent.Handle(ctx, "rename", map[string]any{"key": "cfg/old", "newKey": "cfg/new"})
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := agent.Handle(ctx, "get", map[string]any{"key": sourceKey}); err != nil {
    return fmt.Errorf("source %q missing, cannot rename: %w", sourceKey, err)
}

Type guard

func isNotFound(err error) bool {
    return err != nil && strings.Contains(err.Error(), "ETCD_NOT_FOUND")
}

Try / catch

_, err := agent.Handle(ctx, "rename", params)
if isNotFound(err) {
    // key already renamed/deleted elsewhere: log and treat as no-op, or fail the migration step explicitly
}

Prevention

When it happens

Trigger: Calling rename where the source key does not exist in etcd — it was never created, already renamed/deleted by another process, or the key path is wrong (missing prefix, wrong namespace).

Common situations: Typos in key names or missing leading slash; a previous rename already moved the key so a retry hits a missing source; environment mismatch (pointing at a different etcd namespace/cluster than the writer); TTL expiry removed the key.

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/f9b84092da8a5b7a. Report an issue: GitHub.