sipeed/picoclaw · info

deltachat: created chatmail account %q on %s. Update channel

Error message

deltachat: created chatmail account %q on %s. Update channel_list.deltachat.settings.email from %q to %q, remove the @server bootstrap marker, then run PicoClaw again to use the account

What it means

Not a failure: this is the successful terminal state of the chatmail bootstrap flow, deliberately returned as an error so the channel does not auto-use a randomly generated address. The account exists and its address is known; the operator must pin it in config and remove the '@server' marker.

Source

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

	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)
	}

	return fmt.Errorf(
		"deltachat: created chatmail account %q on %s. Update channel_list.deltachat.settings.email from %q to %q, remove the @server bootstrap marker, then run PicoClaw again to use the account",
		addr,
		server,
		c.config.Email,
		addr,
	)
}

func (c *DeltaChatChannel) cleanupPendingAccount(ctx context.Context, accountID int64) {
	if accountID <= 0 || c.rpc == nil {
		return
	}
	stopCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
	_, _ = c.rpc.call(stopCtx, "stop_ongoing_process", accountID)
	cancel()

	removeCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
	_, _ = c.rpc.call(removeCtx, "remove_account", accountID)

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Copy the generated address quoted in the message
  2. Edit channel_list.deltachat.settings.email: replace the '@server' value with the generated addr
  3. Restart PicoClaw: ensureAccount will find the already-configured account by addr and reuse it

Example fix

# before (channel_list config)
email: "@nine.testrun.org"

# after
email: "bot-1739abcd@nine.testrun.org"
Defensive patterns

Strategy: try-catch

Type guard

var chatmailCreatedPrefix = "deltachat: created chatmail account "

func isChatmailBootstrapDone(err error) bool {
    return err != nil && strings.HasPrefix(err.Error(), chatmailCreatedPrefix)
}

Try / catch

if err := ch.ensureAccount(ctx); err != nil {
    if isChatmailBootstrapDone(err) {
        // success-with-instructions: parse addr, update config, remove '@server' marker
        log.Info("chatmail bootstrap complete; config update required")
        return nil // or surface as actionable info, not a failure
    }
    return err
}

Prevention

When it happens

Trigger: createChatmailBootstrapAccount completes: add_transport_from_qr succeeded and a non-empty addr was read, while channel_list.deltachat.settings.email still holds the '@domain' bootstrap marker.

Common situations: First-time chatmail setup, e.g. email: "@nine.testrun.org" on a fresh data_dir.

Related errors


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