t8y2/dbx · error

ETCD_V2_UNSUPPORTED

ETCD_V2_UNSUPPORTED

Error message

ETCD_V2_UNSUPPORTED: %s is not available on the etcd v2 API

What it means

The v2 runtime's handle() dispatch checks isEtcd3OnlyMethod and rejects methods that exist only in etcd's v3 API (e.g. kv_history, etcd_compact, etcd_defrag, watches, leases) with this coded error. The v2 driver cannot emulate those primitives, so it fails explicitly instead of silently misbehaving.

Source

Thrown at agents/drivers/etcd2-go/main.go:388

	case "etcd_auth_role_get":
		return s.authRoleGet(params)
	case "etcd_auth_role_add":
		return s.authRoleAdd(params)
	case "etcd_auth_role_delete":
		return s.authRoleDelete(params)
	case "etcd_auth_role_grant_permission":
		return s.authRolePermission(params, true)
	case "etcd_auth_role_revoke_permission":
		return s.authRolePermission(params, false)
	case "disconnect":
		s.close()
		return map[string]bool{"ok": true}, nil
	case "shutdown":
		s.close()
		return map[string]bool{"ok": true}, nil
	default:
		if isEtcd3OnlyMethod(method) {
			return nil, fmt.Errorf("ETCD_V2_UNSUPPORTED: %s is not available on the etcd v2 API", method)
		}
		return nil, fmt.Errorf("unknown method: %s", method)
	}
}

func isEtcd3OnlyMethod(method string) bool {
	switch method {
	case "kv_history", "etcd_compact", "etcd_defrag",
		"etcd_lease_list", "etcd_lease_get", "etcd_lease_grant",
		"etcd_lease_keepalive_once", "etcd_lease_revoke":
		return true
	}
	return false
}

func decodeParams(params map[string]json.RawMessage, target any) error {
	if params == nil {
		params = map[string]json.RawMessage{}

View on GitHub (pinned to c0390bff16)

Solutions

  1. Use the etcd3 (gRPC) driver for methods requiring v3 semantics.
  2. Gate the call behind a capability check (isEtcd3OnlyMethod or equivalent) before dispatch.
  3. Rework the operation using v2 primitives where possible (e.g. poll keys instead of watch).

Example fix

// before
handle(v2Session, "etcd_defrag", {})
// after
if !isEtcd3OnlyMethod("etcd_defrag") { handle(v2Session, "etcd_defrag", {}) } // or use the v3 driver
Defensive patterns

Strategy: validation

Validate before calling

if isEtcd3OnlyMethod(method) { return fmt.Errorf("method %s requires the etcd3 driver; v2 driver in use", method) }

Type guard

func v2Capable(method string) bool { return !isEtcd3OnlyMethod(method) }

Try / catch

if err := handle(session, method, params); err != nil && strings.Contains(err.Error(), "ETCD_V2_UNSUPPORTED") {
    return routeToV3Driver(session, method, params)
}

Prevention

When it happens

Trigger: Sending an etcd3-only method name (per isEtcd3OnlyMethod's switch list) to the etcd2 driver's handle(), e.g. calling etcd_compact or kv_history through the v2 agent.

Common situations: Shared client code written against an etcd3 driver pointed at the v2 driver, feature-detection missing, tests like TestEtcd3OnlyMethodsRejected exercising the rejection path.

Related errors


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