{"record":{"id":"c6ef76b951684f2e","repo":"babalae/better-genshin-impact","slug":"autoskip-autoskipconfig","errorCode":null,"errorMessage":"AutoSkip的配置参数需要为AutoSkipConfig类型","messagePattern":"AutoSkip的配置参数需要为AutoSkipConfig类型","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"BetterGenshinImpact/Core/Script/Dependence/Model/RealTimeTimer.cs","lineNumber":53,"sourceCode":"        Name = name;\n    }\n\n    public RealtimeTimer(string name, dynamic config)\n    {\n        Name = name;\n        if (Name == \"AutoPick\")\n        {\n            Config = ScriptObjectConverter.ConvertTo<AutoPickExternalConfig>(config);\n        }\n        else if (Name == \"AutoSkip\")\n        {\n            if (config is AutoSkipConfig)\n            {\n                Config = config;\n            }\n            else \n            {\n                throw new ArgumentException(\"AutoSkip的配置参数需要为AutoSkipConfig类型\");\n            }\n        }\n    }\n}\n","sourceCodeStart":35,"sourceCodeEnd":58,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/Core/Script/Dependence/Model/RealTimeTimer.cs#L35-L58","documentation":"Thrown by the RealtimeTimer constructor when Name equals \"AutoSkip\" but the provided config object is not of type AutoSkipConfig. Unlike AutoPick (which auto-converts via ScriptObjectConverter), AutoSkip requires the caller to pass an already-typed AutoSkipConfig instance — no conversion is attempted.","triggerScenarios":"Constructing new RealtimeTimer(\"AutoSkip\", config) where config is a JObject, ExpandoObject, anonymous type, or any type other than AutoSkipConfig. The check is a strict 'is AutoSkipConfig' type test.","commonSituations":"Deserializing a timer configuration from JSON where the config field is parsed as a generic object/JObject rather than a typed AutoSkipConfig. Migrating from a dynamic config model to typed configs without updating the serialization path.","solutions":["Pre-convert the config: pass ScriptObjectConverter.ConvertTo<AutoSkipConfig>(config) into the constructor.","Ensure your JSON deserialization uses typed settings that map the AutoSkip config field to AutoSkipConfig.","If building programmatically, construct new AutoSkipConfig() and populate its properties directly."],"exampleFix":"// before\nvar timer = new RealtimeTimer(\"AutoSkip\", jObject);\n// after\nvar cfg = ScriptObjectConverter.ConvertTo<AutoSkipConfig>(jObject);\nvar timer = new RealtimeTimer(\"AutoSkip\", cfg);","handlingStrategy":"type-guard","validationCode":"if (name == \"AutoSkip\")\n{\n    var typedConfig = config is AutoSkipConfig existing\n        ? existing\n        : ScriptObjectConverter.ConvertTo<AutoSkipConfig>(config);\n    var timer = new RealtimeTimer(name, typedConfig);\n}","typeGuard":"static bool IsValidAutoSkipConfig(object config) => config is AutoSkipConfig;","tryCatchPattern":"try\n{\n    var timer = new RealtimeTimer(\"AutoSkip\", config);\n}\ncatch (ArgumentException ex) when (ex.Message.Contains(\"AutoSkip\"))\n{\n    // Convert and retry\n    var converted = ScriptObjectConverter.ConvertTo<AutoSkipConfig>(config);\n    var timer = new RealtimeTimer(\"AutoSkip\", converted);\n}","preventionTips":["Always convert dynamic/JObject configs to their target type before passing to RealtimeTimer for AutoSkip.","Use typed deserialization for timer configurations instead of raw JObject."],"tags":["configuration","type-mismatch","script-api","argument-validation"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}