iflytek/astron-agent · error

tenant bootstrap API key conflicts with an unmanaged…

Error message

tenant bootstrap API key conflicts with an unmanaged credential

What it means

When the bootstrap api_key row is not managed (missing the managed marker), it is treated as an unmanaged credential. The function tolerates it only if the row is valid, not deleted, and its secret matches the configured secret via constant-time compare; otherwise it reports a conflict between the bootstrap API key and an unmanaged credential.

Solutions

  1. Align the configured bootstrap secret with the existing row's secret (or vice versa) so they match
  2. Migrate the existing row into the managed flow by adding the managed marker and correct secret
  3. Choose a new api_key value with no pre-existing row
  4. Clean up the soft-deleted/NULL-flagged conflicting row before re-running bootstrap

Example fix

// before
conf = {APIKey: "ak-1", Secret: "new-secret"} // DB row has old-secret, unmanaged
// after
conf = {APIKey: "ak-1", Secret: "old-secret"} // matches unmanaged row, or re-key
Defensive patterns

Strategy: validation

Validate before calling

var secret string; var marker string
err := db.QueryRow(`SELECT secret, marker FROM tb_app WHERE api_key = ?`, apiKey).Scan(&secret, &marker)
if err == nil && marker != managedMarker && secret != configuredSecret { return errors.New("api_key conflicts with unmanaged credential") }

Try / catch

if err != nil && strings.Contains(err.Error(), "unmanaged credential") { rotateBootstrapKey(ctx, creds); return reconcileBootstrap(ctx, creds) }

Prevention

When it happens

Trigger: A tb_app row with the same api_key exists but was created outside the bootstrap flow (no tenantBootstrapManagedMarker), and either its secret differs from credentials.Secret, its secret/flags are NULL, or the row is soft-deleted.

Common situations: The api_key was issued manually or by a legacy provisioning tool, credentials were rotated in config but not in the DB, or the managed marker was lost after a manual DB edit.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12). Data as JSON: /api/errors/fc28645d4d7749ce. Report an issue: GitHub.

Appendix: source

Thrown at core/tenant/tools/database/bootstrap_credentials.go:196

		return false, fmt.Errorf("check tenant bootstrap API key ownership failed: %w", err)
	}

	var unmanagedSecret sql.NullString
	var unmanagedIsDelete sql.NullBool
	err = transaction.QueryRowContext(
		ctx,
		`SELECT api_secret, is_delete
	FROM tb_auth
	WHERE app_id = ? AND api_key = ? AND COALESCE(extend, '') <> ?
	LIMIT 1 FOR UPDATE`,
		credentials.TenantID,
		credentials.APIKey,
		tenantBootstrapManagedMarker,
	).Scan(&unmanagedSecret, &unmanagedIsDelete)
	if err == nil {
		if !unmanagedSecret.Valid || !unmanagedIsDelete.Valid || unmanagedIsDelete.Bool ||
			subtle.ConstantTimeCompare([]byte(unmanagedSecret.String), []byte(credentials.Secret)) != 1 {
			return false, errors.New("tenant bootstrap API key conflicts with an unmanaged credential")
		}
		return true, nil
	}
	if err != nil && !errors.Is(err, sql.ErrNoRows) {
		return false, fmt.Errorf("check tenant bootstrap managed credential failed: %w", err)
	}
	return false, nil
}

func adoptTenantBootstrapCredential(
	ctx context.Context,
	transaction bootstrapTransaction,
	credentials config.TenantBootstrapCredentials,
	now string,
) error {
	// A strong pair explicitly configured by the deployment may already have
	// been created through Tenant's public API on an older release. Because it
	// belongs to the reserved app and exactly matches the current deployment

View on GitHub (pinned to 5e758547a8)