MHSanaei/3x-ui · error
node is disabled
Error message
node is disabled
What it means
Returned by NodeService.GetWebCertFiles when the node row exists but n.Enable is false. Disabled nodes have no live Remote/runtime handle by design, so the panel refuses to contact them and fails fast with this message before touching the runtime manager.
Source
Thrown at internal/web/service/node.go:776
if err := db.Model(model.Node{}).Where("id = ?", id).Update("enable", enable).Error; err != nil {
return err
}
if mgr := runtime.GetManager(); mgr != nil {
mgr.InvalidateNode(id)
}
return nil
}
// GetWebCertFiles asks a node for its own web TLS certificate/key file paths,
// used by "Set Cert from Panel" so a node-assigned inbound gets paths that
// exist on the node rather than the central panel. See issue #4854.
func (s *NodeService) GetWebCertFiles(id int) (*runtime.WebCertFiles, error) {
n, err := s.GetById(id)
if err != nil || n == nil {
return nil, fmt.Errorf("node not found")
}
if !n.Enable {
return nil, fmt.Errorf("node is disabled")
}
mgr := runtime.GetManager()
if mgr == nil {
return nil, fmt.Errorf("runtime manager unavailable")
}
remote, err := mgr.RemoteFor(n)
if err != nil {
return nil, err
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
return remote.GetWebCertFiles(ctx)
}
// NodeUpdateResult reports the outcome of triggering a panel self-update on one
// node so the UI can show per-node success/failure for a bulk request.
type NodeUpdateResult struct {
Id int `json:"id"`View on GitHub (pinned to ad32144c42)
Solutions
- Re-enable the node (toggle in the nodes list) once it is healthy, then retry the cert fetch.
- If the node is intentionally disabled, enter cert paths manually on the inbound instead of fetching from the node.
- Make automation skip disabled nodes: check the node's enable flag before calling cert/node RPCs.
- Investigate why the node was disabled — repeated health failures usually point at the connectivity issues behind errors 100-105.
Example fix
// before: node id=5 disabled // err: node is disabled // after: enable node 5 in the panel (and confirm it is reachable), then retry getWebCertFiles
Defensive patterns
Strategy: validation
Validate before calling
n, err := nodeSvc.GetById(id)
if err != nil || n == nil { return errors.New("node not found") }
if !n.Enable { return errors.New("node disabled: enable it or use manual cert paths") } Type guard
func isNodeDisabled(err error) bool {
return err != nil && strings.Contains(err.Error(), "node is disabled")
} Try / catch
files, err := nodeSvc.GetWebCertFiles(id)
if err != nil {
if isNodeDisabled(err) {
return nil, errUnavailable("node disabled; enable node or enter cert paths manually")
}
return nil, err
} Prevention
- Have UI/automation check the node's enable flag before offering node-dependent actions.
- Re-enable nodes promptly after maintenance so cert and sync flows recover.
- Investigate WHY a node is disabled — persistent disablement usually traces back to the connectivity errors (100-105).
When it happens
Trigger: Calling getWebCertFiles (Set Cert from Panel) for a node whose Enable toggle is off — disabled temporarily for maintenance, disabled because it was offline, or never re-enabled after setup.
Common situations: Admin disabled the node during an incident and the UI still offers cert actions on its inbounds; automation hitting the endpoint for all nodes regardless of enable state.
Related errors
- node not found
- The new username and password are empty
- tg_id must be a positive integer
- token not found
- invalid metric
AI-assisted analysis of MHSanaei/3x-ui@ad32144c42 (2026-08-15).
Data as JSON: /api/errors/c0439b21ffd7454b.
Report an issue: GitHub.