chenhg5/cc-connect · error

dingtalk: robot_code is required (or client_id)

Error message

dingtalk: robot_code is required (or client_id)

What it means

After falling back robotCode to client_id, New validates that a robot code was resolved. This error means neither 'robot_code' nor a usable 'client_id' was available, so the platform cannot identify the robot in API calls (e.g. messageFiles/download requires robotCode). In practice it is reached when client_id was empty but client_secret was set, or robot_code was set to a non-string/empty value.

Source

Thrown at platform/dingtalk/dingtalk.go:112

	degradeMu       sync.Mutex
}

func New(opts map[string]any) (core.Platform, error) {
	clientID, _ := opts["client_id"].(string)
	clientSecret, _ := opts["client_secret"].(string)
	robotCode, _ := opts["robot_code"].(string)
	allowFrom, _ := opts["allow_from"].(string)
	core.CheckAllowFrom("dingtalk", allowFrom)
	shareSessionInChannel, _ := opts["share_session_in_channel"].(bool)
	if clientID == "" || clientSecret == "" {
		return nil, fmt.Errorf("dingtalk: client_id and client_secret are required")
	}
	if robotCode == "" {
		robotCode = clientID // fallback to client_id if robot_code not specified
	}
	// Validate robot_code format (should not be empty after fallback)
	if robotCode == "" {
		return nil, fmt.Errorf("dingtalk: robot_code is required (or client_id)")
	}

	reactionEmoji, _ := opts["reaction_emoji"].(string)
	reactionEmoji = strings.TrimSpace(reactionEmoji)
	if reactionEmoji == "" {
		reactionEmoji = defaultReactionEmoji
	}
	if strings.EqualFold(reactionEmoji, "none") {
		reactionEmoji = ""
	}
	doneEmoji, _ := opts["done_emoji"].(string)
	doneEmoji = strings.TrimSpace(doneEmoji)
	if strings.EqualFold(doneEmoji, "none") {
		doneEmoji = ""
	}

	// agent_id is required for work notifications API (numeric type)
	// Try to read as int64 first, then float64 (JSON numbers), fallback to 0

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Provide 'client_id' (AppKey) — robotCode will automatically fall back to it.
  2. Or explicitly set 'robot_code' to your robot's code if it differs from the client_id.
  3. Validate that both values are non-empty strings before calling New.

Example fix

// before
opts := map[string]any{"client_secret": secret, "robot_code": ""}
// after
opts := map[string]any{"client_id": clientID, "client_secret": secret} // robot_code defaults to client_id
Defensive patterns

Strategy: validation

Validate before calling

func validateDingtalkRobot(opts map[string]any) error {
    id, _ := opts["client_id"].(string)
    rc, _ := opts["robot_code"].(string)
    if id == "" && rc == "" {
        return fmt.Errorf("dingtalk: provide robot_code or client_id")
    }
    return nil
}

Type guard

func optString(opts map[string]any, key string) (string, bool) {
    s, ok := opts[key].(string)
    return s, ok && s != ""
}

Prevention

When it happens

Trigger: dingtalk.New(opts) where 'robot_code' is absent/empty AND the fallback source 'client_id' is also empty (or not a string). Notably unreachable when client_id is valid, since robotCode falls back to it.

Common situations: Config with only client_secret set; client_id misspelled or typed as a non-string; robot_code explicitly set to "" in an attempt to 'disable' it while credentials are also incomplete.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/1902df2aa9ff1acb. Report an issue: GitHub.