MHSanaei/3x-ui · error

node has no API token configured

Error message

node has no API token configured

What it means

Remote.do refuses to send when the node record has no ApiToken AND TlsVerifyMode is not 'mtls'. Every node-auth mode except mutual TLS uses a bearer token, so an empty token means the request cannot be authenticated and would surface later as a confusing 401. Failing client-side with this explicit error pinpoints the missing configuration. mtls nodes are exempt because the client certificate itself carries identity.

Source

Thrown at internal/web/runtime/remote.go:181

		return "", fmt.Errorf("invalid node port %d", r.node.Port)
	}
	bp := r.node.BasePath
	if !strings.HasSuffix(bp, "/") {
		bp += "/"
	}
	u := &url.URL{
		Scheme: scheme,
		Host:   net.JoinHostPort(addr, strconv.Itoa(r.node.Port)),
		Path:   bp,
	}
	return u.String(), nil
}

func (r *Remote) do(ctx context.Context, method, path string, body any) (*envelope, error) {
	// mtls nodes authenticate via the client certificate, so a bearer token is
	// optional for them; every other mode still requires one.
	if r.node.ApiToken == "" && r.node.TlsVerifyMode != "mtls" {
		return nil, errors.New("node has no API token configured")
	}

	base, err := r.baseURL()
	if err != nil {
		return nil, err
	}
	target := base + strings.TrimPrefix(path, "/")

	var (
		bodyBytes   []byte
		contentType string
	)
	switch b := body.(type) {
	case nil:
	case url.Values:
		bodyBytes = []byte(b.Encode())
		contentType = "application/x-www-form-urlencoded"
	default:

View on GitHub (pinned to ad32144c42)

Solutions

  1. Copy the API token from the remote panel and save it on the node record
  2. If the node genuinely uses mutual TLS, set TlsVerifyMode='mtls' so certificate auth is used instead
  3. Validate at node-save time that token is non-empty unless mode is mtls, so the error surfaces in the form rather than at dispatch

Example fix

// before
node.ApiToken = ""
node.TlsVerifyMode = ""

// after
node.ApiToken = remoteToken // from remote panel
// or: node.TlsVerifyMode = "mtls" with client cert configured
Defensive patterns

Strategy: validation

Validate before calling

if node.ApiToken == "" && node.TlsVerifyMode != "mtls" {
    return errors.New("save an API token on the node, or switch it to mtls auth")
}

Try / catch

if _, err := remote.Do(ctx, method, path, body); err != nil {
    if strings.Contains(err.Error(), "no API token configured") {
        // fill node.ApiToken from the remote panel and retry once
    }
}

Prevention

When it happens

Trigger: Creating a node without pasting its API token (empty string saved); token field cleared during an edit; switching a node from mtls to token mode without adding the token.

Common situations: New node setup where the operator skipped the token step; copy-paste dropping the token; node templates defaulting to empty token.

Related errors


AI-assisted analysis of MHSanaei/3x-ui@ad32144c42 (2026-08-15). Data as JSON: /api/errors/820c8089723a161f. Report an issue: GitHub.