OpenNHP/opennhp · error

keystore: find agent by pubkey

Error message

keystore: find agent by pubkey: %w

What it means

FindAgentByPublicKey wraps failures of the COUNT(*) query that checks whether a base64 public key belongs to an active, non-expired agent. Only DB-level failures produce this error; a zero count returns (false, nil). It is consulted by the noise-layer peer validation fallback, so an error here can block peer authentication.

Solutions

  1. Log the wrapped driver error to determine if it is 'no such table', 'database is locked', or 'database is closed'.
  2. Run schema migration before starting the noise-layer listener that calls this function.
  3. Enable WAL mode and busy_timeout on the SQLite handle to reduce lock contention.
  4. Confirm the server process owns/opens the DB file it is configured to use.
  5. Retry transient lock errors with backoff at the caller (peer validation) level.

Example fix

null
Defensive patterns

Strategy: retry

Validate before calling

if pubKeyBase64 == "" { return false, errors.New("empty public key") }
if err := db.Ping(); err != nil { return false, err }

Type guard

ok, err := store.FindAgentByPublicKey(pubKey)
if err != nil {
    // fail closed, but log the wrapped cause
    log.Errorf("peer validation failed: %v", err)
    return false
}

Try / catch

ok, err := store.FindAgentByPublicKey(pub)
if err != nil {
    if isLockTimeout(err) { return store.FindAgentByPublicKey(pub) } // one retry
    return false, err
}

Prevention

When it happens

Trigger: Calling FindAgentByPublicKey(pubKeyBase64) when the DB connection is closed, the agent_keys table is missing, the database is locked, or the driver returns a general query error.

Common situations: SQLite file locked during backup jobs; schema mismatch after an upgrade; disk-full conditions preventing even a SELECT from executing; running the server against an uninitialized config path.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07). Data as JSON: /api/errors/aa35b7b1cd5f729e. Report an issue: GitHub.

Appendix: source

Thrown at endpoints/server/keystore.go:464

		rec.ExpiresAt = &expiresAt.Int64
	}
	return rec, nil
}

// FindAgentByPublicKey returns true if the given base64-encoded public key
// is registered, active, and not expired. This is the gate consulted by
// the noise-layer peer validation fallback; an expired key behaves as if
// the agent were never registered.
func (s *AgentKeyStore) FindAgentByPublicKey(pubKeyBase64 string) (bool, error) {
	var count int
	err := s.db.QueryRow(
		`SELECT COUNT(*) FROM agent_keys
		 WHERE public_key = ? AND active = 1
		   AND (expires_at IS NULL OR expires_at > ?)`,
		pubKeyBase64, time.Now().Unix(),
	).Scan(&count)
	if err != nil {
		return false, fmt.Errorf("keystore: find agent by pubkey: %w", err)
	}
	return count > 0, nil
}

// IsAgentRegistered returns true if the user+device pair has an active,
// non-expired registered key.
func (s *AgentKeyStore) IsAgentRegistered(userId, deviceId string) (bool, error) {
	var count int
	err := s.db.QueryRow(
		`SELECT COUNT(*) FROM agent_keys
		 WHERE usr_id = ? AND dev_id = ? AND active = 1
		   AND (expires_at IS NULL OR expires_at > ?)`,
		userId, deviceId, time.Now().Unix(),
	).Scan(&count)
	if err != nil {
		return false, fmt.Errorf("keystore: check agent registered: %w", err)
	}
	return count > 0, nil

View on GitHub (pinned to 6e04ca5ff0)