sipeed/picoclaw · error

deltachat create chatmail account on %s: %w

Error message

deltachat create chatmail account on %s: %w

What it means

Thrown by createChatmailBootstrapAccount when the JSON-RPC call add_transport_from_qr fails. This call passes a DCACCOUNT QR (built by buildChatmailAccountQR) to the spawned deltachat-rpc-server, which registers a brand-new account on the chatmail server over the network. It runs under configureTimeout (90s, deltachat.go:38); unless created=true, the deferred cleanupPendingAccount removes the half-created account, so retries are safe.

Source

Thrown at pkg/channels/deltachat/deltachat.go:1060

		return fmt.Errorf("deltachat add_account decode: %w", decodeErr)
	}

	created := false
	defer func() {
		if !created {
			c.cleanupPendingAccount(context.Background(), accountID)
		}
	}()

	confCtx, cancel := context.WithTimeout(ctx, configureTimeout)
	defer cancel()
	if _, callErr := c.rpc.call(
		confCtx,
		"add_transport_from_qr",
		accountID,
		buildChatmailAccountQR(server),
	); callErr != nil {
		return fmt.Errorf("deltachat create chatmail account on %s: %w", server, callErr)
	}
	created = true

	if profileErr := c.applyProfileConfig(ctx, accountID); profileErr != nil {
		logger.WarnCF(
			"deltachat",
			"Could not apply profile config to new account",
			map[string]any{"error": profileErr.Error()},
		)
	}

	addr, err := c.getAccountConfigString(ctx, accountID, "addr")
	if err != nil {
		return fmt.Errorf("deltachat created account on %s, but could not read generated email: %w", server, err)
	}
	addr = strings.TrimSpace(addr)
	if addr == "" {
		return fmt.Errorf("deltachat created account on %s, but generated email is empty", server)

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Check the deltachat-rpc-server stderr output (forwarded to debug logs via logWriter) for the core's real reason
  2. Verify the domain is a real chatmail instance and egress to it (HTTPS/IMAP/SMTP) is allowed from this host
  3. Upgrade deltachat-rpc-server to a release that supports add_transport_from_qr, then retry
  4. Simply retry the run: the failure path already removed the pending account, so state is clean
  5. If the error wraps context.DeadlineExceeded, raise configureTimeout (deltachat.go:38) or fix the slow network path

Example fix

// before (deltachat.go:38)
const configureTimeout = 90 * time.Second

// after
const configureTimeout = 180 * time.Second
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight: can we reach the chatmail server before bootstrapping?
func chatmailReachable(server string) bool {
    conn, err := net.DialTimeout("tcp", net.JoinHostPort(server, "443"), 5*time.Second)
    if err != nil {
        return false
    }
    _ = conn.Close()
    return true
}

Type guard

func isRPCGone(err error) bool {
    return errors.Is(err, context.DeadlineExceeded) ||
        strings.Contains(err.Error(), "rpc closed") ||
        strings.Contains(err.Error(), "connection closed")
}

Try / catch

if err := ch.ensureAccount(ctx); err != nil {
    if errors.Is(err, context.DeadlineExceeded) {
        // network-bound registration timed out; retry is safe (pending account was cleaned up)
    }
    return err
}

Prevention

When it happens

Trigger: channel_list.deltachat.settings.email contains the '@server' bootstrap marker (parseDeltaChatEmailSetting -> bootstrap=true) and then: the chatmail domain is wrong/unreachable, the server rejects registration, deltachat-rpc-server returns a JSON-RPC error object, the child process dies (readLoop EOF -> failAll -> 'rpc closed: ...'), or the 90s confCtx deadline expires.

Common situations: Typo'd chatmail domain (e.g. @nine.testrun.or), sandboxed host without egress to the chatmail server, an outdated deltachat-rpc-server build that lacks add_transport_from_qr, a slow server exceeding 90s, or DC_ACCOUNTS_PATH on a read-only/full volume making the child crash mid-registration.

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/1f9ec58a462eb6c4. Report an issue: GitHub.