{"record":{"id":"ca2687ff4b4701ff","repo":"PHPOffice/PhpSpreadsheet","slug":"invalid-operation-for-errors-cf-rule-wizard","errorCode":null,"errorMessage":"Invalid Operation for Errors CF Rule Wizard","messagePattern":"Invalid Operation for Errors CF Rule Wizard","errorType":"exception","errorClass":"PhpOffice\\PhpSpreadsheet\\Exception","httpStatus":null,"severity":"error","filePath":"src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/Errors.php","lineNumber":84,"sourceCode":"        ) {\n            throw new Exception('Conditional is not an Errors CF Rule conditional');\n        }\n\n        $wizard = new self($cellRange);\n        $wizard->style = $conditional->getStyle();\n        $wizard->stopIfTrue = $conditional->getStopIfTrue();\n        $wizard->inverse = $conditional->getConditionType() === Conditional::CONDITION_CONTAINSERRORS;\n\n        return $wizard;\n    }\n\n    /**\n     * @param mixed[] $arguments\n     */\n    public function __call(string $methodName, array $arguments): self\n    {\n        if (!array_key_exists($methodName, self::OPERATORS)) {\n            throw new Exception('Invalid Operation for Errors CF Rule Wizard');\n        }\n\n        $this->inverse(self::OPERATORS[$methodName]);\n\n        return $this;\n    }\n}\n","sourceCodeStart":66,"sourceCodeEnd":92,"githubUrl":"https://github.com/PHPOffice/PhpSpreadsheet/blob/65b080eef4d9fd11a5796135ab145883e5c3d6a6/src/PhpSpreadsheet/Style/ConditionalFormatting/Wizard/Errors.php#L66-L92","documentation":"The Errors wizard exposes its modes through __call against an OPERATORS map with exactly two keys: 'isError' and 'notError'. Any other method name throws - common attempts include hasError(), isErr(), notErrors() or error().","triggerScenarios":"->hasError(); ->notErrors() (plural - not a key); ->isErrors(); dynamically built method names that are not exactly isError or notError.","commonSituations":"Developers guessing symmetric or more descriptive names; IDE autocompletion from the @method docblock not being used; fluent chains assembled from config keys.","solutions":["Use only isError() or notError()","Validate dynamic method names against ['isError', 'notError'] before invoking","Catch PhpSpreadsheetException around dynamic calls","Note the inverse mode can also be chosen at construction: newRule(Wizard::ERRORS) vs newRule(Wizard::NOT_ERRORS)"],"exampleFix":"// before\n$errorsWizard = (new Wizard('A1:E10'))->newRule(Wizard::ERRORS);\n$errorsWizard->hasError();   // throws\n\n// after\n$errorsWizard->isError();    // or ->notError()","handlingStrategy":"validation","validationCode":"$allowed = ['isError', 'notError'];\n$method = $config['errorMode'];\nif (!in_array($method, $allowed, true)) {\n    throw new InvalidArgumentException('Unknown Errors mode: ' . $method);\n}\n$wizard->$method();","typeGuard":null,"tryCatchPattern":"use PhpOffice\\PhpSpreadsheet\\Exception as PhpSpreadsheetException;\n\ntry {\n    $wizard->$method();\n} catch (PhpSpreadsheetException $e) {\n    throw new InvalidArgumentException('Invalid Errors mode: ' . $method, 0, $e);\n}","preventionTips":["Only isError() and notError() exist on this wizard","Avoid plural/guessed variants like notErrors() or hasError()","Pick the mode at construction too: newRule(Wizard::ERRORS) vs newRule(Wizard::NOT_ERRORS)","Whitelist mode strings arriving from config or user input"],"tags":["php","phpspreadsheet","conditional-formatting","wizard","errors","magic-methods"],"backgroundTag":"invalid-fluent-builder-method","analyzedSha":"65b080eef4d9fd11a5796135ab145883e5c3d6a6","analyzedAt":"2026-08-17T05:40:41.646Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}