Wei-Shaw/sub2api · error · ErrDingTalkV1AppTypeMismatch
dingtalk: internal_only requires app_type=internal
Error message
dingtalk: internal_only requires app_type=internal
What it means
Returned by ValidateDingTalkConfig in backend/internal/config/validate_dingtalk.go when CorpRestrictionPolicy is "internal_only" but AppType is not "internal". The internal_only security model (Plan A) relies on DingTalk 'enterprise internal app' semantics — only employees of the app's own corporation can complete OAuth — so the config must declare app_type=internal. The old requirement for a non-empty InternalCorpID (V3) was removed; the field remains optional and unused for constraint.
Source
Thrown at backend/internal/config/validate_dingtalk.go:13
// Package config 包含钉钉连接配置的校验逻辑。
//
// internal_only 模式安全模型(方案 A):
// 不再要求 admin 填写 InternalCorpID 做二次 corpID 比对。
// 安全边界由钉钉"企业内部应用"类型本身保证——只有应用所属企业的员工才能完成 OAuth,
// 因此 ValidateDingTalkConfig 只要求 app_type=internal(V1),不再要求 InternalCorpID 非空(原 V3 已删除)。
// InternalCorpID 字段保留,admin 可选填;若填写,checkDingTalkCorpAllowed 不会使用它做约束。
package config
import "errors"
var (
ErrDingTalkV1AppTypeMismatch = errors.New("dingtalk: internal_only requires app_type=internal")
ErrDingTalkV4InvalidAppKind = errors.New("dingtalk: dingtalk_app_kind must be internal_app")
)
func ValidateDingTalkConfig(cfg DingTalkConnectConfig) error {
if !cfg.Enabled {
return nil
}
if cfg.DingTalkAppKind != "internal_app" {
return ErrDingTalkV4InvalidAppKind
}
if cfg.CorpRestrictionPolicy == "internal_only" {
if cfg.AppType != "internal" {
return ErrDingTalkV1AppTypeMismatch
}
}
return nil
}
View on GitHub (pinned to 073e92d171)
Solutions
- Set app_type=internal in the dingtalk config section (and keep dingtalk_app_kind=internal_app).
- If you intentionally use a non-internal app, change corp_restriction_policy away from "internal_only" (e.g. a policy supported for that app type).
- If you relied on the old InternalCorpID check, remove it — it is no longer required nor used as a constraint.
- Re-run the config validator / restart and confirm the error is gone.
Example fix
# before dingtalk: enabled: true dingtalk_app_kind: internal_app corp_restriction_policy: internal_only app_type: "" # or "corp" internal_corp_id: "dingxxxx" # legacy, no longer sufficient # after dingtalk: enabled: true dingtalk_app_kind: internal_app corp_restriction_policy: internal_only app_type: internal
Defensive patterns
Strategy: validation
Validate before calling
func validDingTalkCfg(cfg DingTalkConnectConfig) error {
if !cfg.Enabled { return nil }
if cfg.DingTalkAppKind != "internal_app" { return ErrDingTalkV4InvalidAppKind }
if cfg.CorpRestrictionPolicy == "internal_only" && cfg.AppType != "internal" {
return ErrDingTalkV1AppTypeMismatch
}
return nil
} Try / catch
if err := config.ValidateDingTalkConfig(cfg); err != nil {
if errors.Is(err, config.ErrDingTalkV1AppTypeMismatch) {
log.Fatalf("config: set dingtalk app_type=internal (or change corp_restriction_policy): %v", err)
}
log.Fatalf("config: invalid dingtalk config: %v", err)
} Prevention
- Run the backend's config validation command (or a pre-deploy dry run) before restarting with new dingtalk settings.
- Codify allowed combos in config templates: internal_only always pairs with app_type=internal and dingtalk_app_kind=internal_app.
- After upgrades, re-read the config package comments — the InternalCorpID requirement (old V3) was deliberately removed; stale configs relying on it now fail differently.
- Add a CI check that lints config files against ValidateDingTalkConfig.
When it happens
Trigger: Starting the backend with dingtalk config where corp_restriction_policy=internal_only and app_type is empty, "corp", or any value other than "internal"; also fails startup if dingtalk_app_kind != "internal_app" (ErrDingTalkV4InvalidAppKind, checked first). Only cfg.Enabled=true configurations are validated.
Common situations: Copying a config from an older deployment that used app_type values like "corp" or left app_type unset; upgrading to the version where V3 corpID comparison was replaced by V1 app_type check; mixing settings from a third-party (服务商) DingTalk app with internal_only policy.
Related errors
- 缺少 accessToken/access_token
- userinfo_failed
- auth.dingtalk.callbackMissingToken
- 空 JSON 内容
- agent identity 缺少必要字段
AI-assisted analysis of Wei-Shaw/sub2api@073e92d171 (2026-08-15).
Data as JSON: /api/errors/6e675bacaf98714b.
Report an issue: GitHub.