Skip to content

Troubleshooting Guide

Common issues and solutions when working with Pubky.


Symptom: A user public key does not resolve, so apps cannot find that user’s Homeserver.

A user’s PKARR record is published under the user’s own public key. The record contains a _pubky pointer whose target is the Homeserver public key. So signer.pkdns.publishHomeserverForce(homeserverPk) signs and publishes the record for signer.publicKey; homeserverPk is the value stored in that record, not the DHT key being published.

Common Causes:

  1. User Record Not Published or Points to the Wrong Homeserver

    Terminal window
    # Verify the user's record exists on the DHT
    curl -fsI https://pkarr.pubky.app/<your-public-key> >/dev/null && echo "on DHT" || echo "NOT on DHT"

    Solution: Explicitly publish the user’s _pubky Homeserver pointer. Signup normally does this for you; use force publish when setting the pointer manually, repairing a wrong or missing pointer, or migrating to a different Homeserver. Force publish means “write this pointer now”, even if the existing record is still fresh:

    await signer.pkdns.publishHomeserverForce(homeserverPk);
  2. Record Expired (TTL)

    • PKARR records need periodic refresh to stay easy to discover
    • Solution: Use stale-aware publishing for routine maintenance. It checks the existing record age first and no-ops while the record is fresh, then republishes once the SDK considers it stale (default: older than 1 hour). Pass homeserverPk when you need missing records to be recreated; omitting it can only reuse a Homeserver target found in the existing record.
    // Periodically check whether the record is stale before republishing
    setInterval(
    async () => {
    await signer.pkdns.publishHomeserverIfStale(homeserverPk);
    },
    2 * 60 * 60 * 1000,
    ); // Every 2 hours
  3. DHT Propagation Delay

    • Records take time to propagate (usually < 5 minutes)
    • Solution: Wait a few minutes after publishing, then retry
  4. Incorrect Public Key Format

    • Public keys must be z-base-32 encoded
    • Solution: Verify key format matches: z4e8s17cou9qmuwen8p1556jzhf1wktmzo6ijsfnri9c4hnrdfty

Debugging Commands:

Terminal window
# Check if PKARR relay has your record
curl "https://pkarr.pubky.org/<public-key>"
# Check DNS resolution via PKDNS
dig @pkdns.pkarr.org <public-key>
# Test with Pubky CLI
pubky-cli tools verify-pkarr <public-key>

Symptom: SDK operations fail, timeout, or refuse connection

Common Causes:

  1. HTTPS Not Configured

    • Homeservers REQUIRE HTTPS (not HTTP)
    • Solution: Configure TLS certificate:
    Terminal window
    # Using Let's Encrypt
    certbot --nginx -d yourdomain.com
  2. Firewall Blocking Ports

    • Default ports: 6287 (user API), 6288 (admin API)
    • Solution: Open firewall ports:
    Terminal window
    # UFW example
    sudo ufw allow 6287/tcp
    sudo ufw allow 6288/tcp
  3. Homeserver Not Running

    • Solution: Verify Homeserver is running:
    Terminal window
    # Check process
    ps aux | grep pubky-homeserver
    # Check logs
    journalctl -u pubky-homeserver -f
  4. PKDNS Resolution Failure

    • Browser can’t resolve public-key domain
    • Solution: Use PKDNS-enabled resolver or DoH:
    // In browser, use full HTTPS URL
    const url = `https://your-homeserver.com/pub/...`;

Test Connection:

Terminal window
# Direct test
curl https://your-homeserver.com/
# Via public key (requires PKDNS)
curl $(pkdns resolve <public-key>)/

See Authentication for how Pubky authentication works.

”Invalid Signature” or “Authentication Failed”

Section titled “”Invalid Signature” or “Authentication Failed””

Symptom: SDK operations rejected with authentication errors

Common Causes:

  1. Recovery File Corrupted

    • File is damaged or incorrectly decrypted
    • Solution: Restore from backup or regenerate keys
  2. Wrong Passphrase

    • Recovery file passphrase is incorrect
    • Solution: Verify passphrase, use correct one
  3. Session Expired

    • Sessions have TTL (typically 24 hours)
    • Solution: Sign in again:
    const session = await signer.signin();
  4. Clock Skew

    • System time is significantly wrong
    • Solution: Sync system clock:
    Terminal window
    # Linux/macOS
    sudo ntpdate -s time.nist.gov
    # Or use NTP service
    sudo systemctl restart systemd-timesyncd

Debug Authentication:

// Force re-authentication
await session.signout();
const newSession = await signer.signin();

Symptom: docker compose up fails or containers crash

Common Causes:

  1. Port Conflicts

    • Another service using required ports
    • Solution: Check and free ports:
    Terminal window
    # Find what's using ports
    sudo lsof -i :4173 # Homeserver
    sudo lsof -i :6881 # PKARR relay
    sudo lsof -i :8000 # Nexus
    # Kill conflicting process or change ports in .env
  2. Insufficient Resources

    • Docker doesn’t have enough memory/CPU
    • Solution: Increase Docker resources:
    • Docker Desktop → Settings → Resources → Memory: 8GB+
  3. Environment Variables Missing

    • .env file not configured
    • Solution: Copy and configure:
    Terminal window
    cp .env.example .env
    # Edit .env with your settings
  4. Volume Permission Issues

    • Docker can’t write to volumes
    • Solution: Fix permissions:
    Terminal window
    sudo chown -R $USER:$USER ./data

Debug Docker:

Terminal window
# View logs
docker compose logs -f
# Check container status
docker compose ps
# Restart services
docker compose restart
# Full reset
docker compose down -v
docker compose up -d

Symptom: Nexus or Homeserver can’t connect to Postgres/Neo4j

Solution:

Terminal window
# Check database containers are running
docker compose ps postgres neo4j redis
# Restart database services
docker compose restart postgres neo4j redis
# Check database logs
docker compose logs postgres
docker compose logs neo4j

Symptom: Can’t store or delete data on Homeserver

Common Causes:

  1. Invalid Path

    • Path must start with /pub/ for public data
    • Solution: Use correct path format:
    await session.storage.putText("/pub/myapp/data.json", data);
    // Invalid paths:
    // - "data.json"
    // - "/myapp/data.json"
  2. Data Too Large

    • Homeserver has size limits (default: ~10MB per file)
    • Solution: Split large data or increase Homeserver limit
  3. Rate Limiting

    • Too many requests in short time
    • Solution: Implement backoff:
    async function putWithRetry(
    session: Session,
    path: Path,
    data: string,
    retries = 3,
    ): Promise<void> {
    for (let i = 0; i < retries; i++) {
    try {
    return await session.storage.putText(path, data);
    } catch (error) {
    if (statusCodeOf(error) === 429) {
    await new Promise((resolve) => setTimeout(resolve, 1000 * (i + 1)));
    continue;
    }
    throw error;
    }
    }
    throw new Error("PUT failed after retrying rate limits");
    }
  4. Insufficient Permissions

    • Trying to write to another user’s space
    • Solution: Verify you’re writing to your own pubky

Symptom: Key generation fails in Pubky Ring app

Solutions:

  1. Update the app: Check for latest version
  2. Clear app cache: Settings → Storage → Clear Cache
  3. Reinstall: Uninstall and reinstall (backup recovery phrase first!)

Symptom: Pubky Ring doesn’t authorize app requests

Solutions:

  1. Check app URL: Ensure correct app origin
  2. Re-scan QR code: Try authorization flow again
  3. Check Ring permissions: Ensure app has necessary permissions

Symptom: Discovery takes a long time

Solutions:

  1. Use PKARR relay: Faster than direct DHT:

    const client = new Client({
    pkarr: {
    relays: ["https://pkarr.pubky.org"],
    },
    });
    const pubky = Pubky.withClient(client);
  2. Cache aggressively: Store resolved Homeserver public keys:

    async function getCachedHomeserver(
    pubky: Pubky,
    userPublicKey: string,
    ): Promise<PublicKey | undefined> {
    const cached = homeserverCache.get(userPublicKey);
    if (cached) return cached;
    const user = PublicKey.from(userPublicKey);
    const homeserver = await pubky.getHomeserverOf(user);
    if (homeserver) {
    homeserverCache.set(userPublicKey, homeserver);
    }
    return homeserver;
    }
  3. Use local PKDNS: Run your own PKDNS server for faster resolution

Symptom: Homeserver operations are slow

Solutions:

  1. Choose geographically close Homeserver
  2. Check Homeserver load: May be overloaded
  3. Use CDN: Cache static data
  4. Optimize request batching: Group operations

Causes: DHT unreachable, record doesn’t exist, network issues

Solutions:

  • Check internet connection
  • Verify record was published
  • Try different PKARR relay
  • Wait for DHT propagation

Causes: PKARR record has no Homeserver entries, DNS resolution failed

Solutions:

  • Verify PKARR record contains Homeserver URL
  • Check PKDNS is working
  • Test direct Homeserver URL access

Causes: Auth session TTL passed

Solutions:

  • Sign in again
  • Implement automatic re-authentication

Causes: Trying to access/modify unauthorized data

Solutions:

  • Check capability tokens
  • Verify you own the data
  • Request proper permissions

When reporting bugs, include:

  1. Environment: OS, browser/platform version, SDK version
  2. Steps to reproduce: Exact sequence that causes the issue
  3. Error messages: Full error text and stack traces
  4. Expected vs actual: What should happen vs what happens
  5. Logs: Relevant logs from Homeserver/client

Example:

## Environment
- OS: macOS 14.2
- SDK: @synonymdev/pubky@0.9.1
- Browser: Chrome 120
## Steps to Reproduce
1. Call `await session.storage.putText('/pub/test/file.json', data)`
2. Observe error
## Error Message

Error: Failed to PUT /pub/test/file.json: 500 Internal Server Error

## Expected
Data should be stored successfully
## Actual
500 error returned

Set Log Level:

// Call once at application startup, before creating Pubky or Client instances.
setLogLevel("debug");

Browser DevTools:

Open DevTools → Network tab → Filter: pubky

Command Line:

Terminal window
# Test PKARR
curl "https://pkarr.pubky.org/<public-key>"
# Test homeserver
curl -v "https://homeserver.com/pub/..."
# Check DNS
dig @8.8.8.8 <public-key>
# Test PKDNS
dig @pkdns.pkarr.org <public-key>

Pubky CLI:

Terminal window
# Check user info
pubky-cli user session ./recovery.file
# Test data operations
pubky-cli user get /pub/test ./recovery.file
# Admin diagnostics
PUBKY_ADMIN_PASSWORD=admin pubky-cli admin info