AlexxIT/go2rtc · error

failed to load hub config

Error message

failed to load hub config: %w

What it means

Wraps a failure from loadHubConfig() during Tuya smart API startup. The hub config (MQTT broker address, credentials, topic routing) is fetched from the Tuya cloud after the webrtc config. If that HTTP call fails, Start() aborts because the MQTT connection cannot be established without it.

Solutions

  1. Log the wrapped inner error to distinguish auth failure vs network vs unmarshal error
  2. Re-check accessId/accessKey and region; rotate credentials if recently changed in the Tuya IoT console
  3. Ensure initToken succeeded with a valid token before hub config fetch
  4. Retry with backoff on transient 5xx / network errors
  5. Update go2rtc if Tuya changed the hub-config API response format

Example fix

// before
if err := c.Start(); err != nil { return err } // opaque failure
// after
if err := c.Start(); err != nil {
    if strings.Contains(err.Error(), "failed to load hub config") {
        // refresh token / re-auth, then retry
        _ = c.initToken()
    }
    return fmt.Errorf("tuya: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: sanity-check credentials/region before Start
if accessID == "" || accessKey == "" { return errors.New("tuya credentials missing") }
if !validRegion(region) { return fmt.Errorf("invalid region %q", region) }

Type guard

func hubConfigValid(cfg *tuya.HubConfig) bool { return cfg != nil && cfg.Broker != "" }

Try / catch

if err := c.Start(); err != nil {
    if strings.Contains(err.Error(), "failed to load hub config") {
        _ = c.initToken() // refresh then retry once
    }
    return err
}

Prevention

When it happens

Trigger: TuyaSmartAPI Start() when loadHubConfig()'s cloud request fails: invalid credentials, wrong region endpoint, token rejected mid-flow, malformed response from Tuya, or network failure between token init and hub-config fetch.

Common situations: Tuya cloud returns 401 because accessKey was rotated while the process held an old token; account moved to a different data center region; transient Tuya API outage; response shape changed after a Tuya API update.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07). Data as JSON: /api/errors/e956959c7e4ea127. Report an issue: GitHub.

Appendix: source

Thrown at pkg/tuya/smart_api.go:310

	}

	return client, nil
}

// WebRTC Flow
func (c *TuyaSmartApiClient) Init() error {
	if err := c.initToken(); err != nil {
		return fmt.Errorf("failed to initialize token: %w", err)
	}

	webrtcConfig, err := c.loadWebrtcConfig()
	if err != nil {
		return fmt.Errorf("failed to load webrtc config: %w", err)
	}

	hubConfig, err := c.loadHubConfig()
	if err != nil {
		return fmt.Errorf("failed to load hub config: %w", err)
	}

	if err := c.mqtt.Start(hubConfig, webrtcConfig, c.skill.WebRTC); err != nil {
		return fmt.Errorf("failed to start MQTT: %w", err)
	}

	if c.skill.LowPower > 0 {
		_ = c.mqtt.WakeUp(c.localKey)
	}

	return nil
}

func (c *TuyaSmartApiClient) GetStreamUrl(streamType string) (streamUrl string, err error) {
	return "", errors.New("not supported")
}

func (c *TuyaSmartApiClient) GetAppInfo() (*AppInfoResponse, error) {

View on GitHub (pinned to c245815e75)