babalae/better-genshin-impact · error · InvalidOperationException

JavaScript的Output输出不是布尔类型

Error message

JavaScript的Output输出不是布尔类型

What it means

Thrown by IsMatchJavaScript when engine.Script.Output exists but 'is not bool' — i.e. Output was set to a number, string, object, or undefined. The contract requires Output to be a JavaScript boolean because the method returns (bool)engine.Script.Output.

Source

Thrown at BetterGenshinImpact/GameTask/AutoArtifactSalvage/AutoArtifactSalvageTask.cs:490

            }
        });
        try
        {
            // 传入输入参数
            engine.Script.ArtifactStat = artifact;

            // 执行JavaScript代码
            await Task.Run(() => engine.Execute(javaScript));

            // 检查是否有输出
            if (!engine.Script.propertyIsEnumerable("Output"))
            {
                throw new InvalidOperationException("JavaScript没有设置Output输出");
            }

            if (engine.Script.Output is not bool)
            {
                throw new InvalidOperationException("JavaScript的Output输出不是布尔类型");
            }

            return (bool)engine.Script.Output;
        }
        catch (ScriptInterruptedException)
        {
            logger.LogWarning("脚本执行超出3秒限制,请使用正确的JS代码(JavaScript execution timeout!)");
            throw;
        }
        catch (ScriptEngineException ex)
        {
            throw new Exception($"JavaScript execution error: {ex.Message}", ex);
        }
    }

    public static bool IsMatchRegularExpression(string affixes, string regularExpression, out string msg)
    {
        Match match = Regex.Match(affixes, regularExpression);

View on GitHub (pinned to a7cb36712d)

Solutions

  1. Make Output a real boolean: 'Output = !!result;' or ensure the comparison yields true/false.
  2. Return explicitly: 'Output = (a.level >= 20);'.
  3. If using a function, ensure every branch returns a boolean.
  4. Validate the JS returns boolean in a sandbox before deploying.

Example fix

// before
Output = (artifact.level >= 20) ? 1 : 0;
// after
Output = artifact.level >= 20;
Defensive patterns

Strategy: validation

Validate before calling

bool OutputIsBooleanShape(string js) =>
    Regex.IsMatch(js, @"Output\s*=\s*(true|false|!!|===|!==|>=|<=|>|<|&&|\|\|)");

Prevention

When it happens

Trigger: JS set 'Output = 1' / 'Output = "true"' / 'Output = {}' / 'Output = result' where result is not a boolean; comparison used '==' against a non-boolean yielding a number; Output assigned from a function that returns undefined.

Common situations: User JS returns a truthy non-bool; JS ported from a language where 0/1 are booleans; missing return statement in the deciding function.

Related errors


AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13). Data as JSON: /api/errors/0c3cca5a07ad6a2e. Report an issue: GitHub.