{"record":{"id":"1ab2573678bde9e4","repo":"yiisoft/yii2","slug":"dbdependency-sql-must-be-set","errorCode":null,"errorMessage":"DbDependency::sql must be set.","messagePattern":"DbDependency::sql must be set\\.","errorType":"exception","errorClass":"InvalidConfigException","httpStatus":null,"severity":"error","filePath":"framework/caching/DbDependency.php","lineNumber":55,"sourceCode":"    /**\n     * @var array the parameters (name => value) to be bound to the SQL statement specified by [[sql]].\n     */\n    public $params = [];\n\n\n    /**\n     * Generates the data needed to determine if dependency has been changed.\n     * This method returns the value of the global state.\n     * @param CacheInterface $cache the cache component that is currently evaluating this dependency\n     * @return mixed the data needed to determine if dependency has been changed.\n     * @throws InvalidConfigException if [[db]] is not a valid application component ID\n     */\n    protected function generateDependencyData($cache)\n    {\n        /** @var Connection $db */\n        $db = Instance::ensure($this->db, Connection::className());\n        if ($this->sql === null) {\n            throw new InvalidConfigException('DbDependency::sql must be set.');\n        }\n\n        if ($db->enableQueryCache) {\n            // temporarily disable and re-enable query caching\n            $db->enableQueryCache = false;\n            $result = $db->createCommand($this->sql, $this->params)->queryOne();\n            $db->enableQueryCache = true;\n        } else {\n            $result = $db->createCommand($this->sql, $this->params)->queryOne();\n        }\n\n        return $result;\n    }\n}\n","sourceCodeStart":37,"sourceCodeEnd":70,"githubUrl":"https://github.com/yiisoft/yii2/blob/66f00d18a29b520f85e8e8f1e32d1e7e7b556cac/framework/caching/DbDependency.php#L37-L70","documentation":"Thrown by yii\\caching\\DbDependency::generateDependencyData() when the dependency is evaluated with its sql property still null. DbDependency invalidates a cache entry by re-running a SQL query and comparing the result, so without a query there is nothing to compare and the configuration is invalid. The check runs lazily at cache-set/evaluation time, not at construction.","triggerScenarios":"Calling Yii::$app->cache->set($key, $data, 0, new DbDependency()) without a sql config key; building the dependency from an array config where the key is misspelled or the whole 'dependency' array is empty; copying a FileDependency/ExpressionDependency config and forgetting to replace the property with sql; serializing/deserializing dependencies in a way that drops properties.","commonSituations":"Adding DB-based invalidation to an existing cache->set() call and omitting the sql; config assembled dynamically from a builder whose sql assignment is skipped for one code path; renaming the property during a refactor to a custom dependency subclass; fixture-based tests constructing dependencies directly.","solutions":["Configure the query: new DbDependency(['sql' => 'SELECT MAX(updated_at) FROM post']).","If building from an array, verify the keys: ['class' => DbDependency::class, 'sql' => ..., 'params' => [...]].","Prefer DbQueryDependency with a Query object when you need composable/portable SQL instead of a raw string.","Add a construction-time assertion or factory method so a dependency is never created without its sql."],"exampleFix":"// before\nYii::$app->cache->set('stats', $stats, 0, new DbDependency()); // sql === null -> throws on evaluation\n\n// after\nYii::$app->cache->set('stats', $stats, 0, new DbDependency([\n    'sql' => 'SELECT MAX(updated_at) FROM stats',\n]));","handlingStrategy":"validation","validationCode":"// Build dependencies through one factory that refuses incomplete config\nfunction dbDependency(string $sql, array $params = []): \\yii\\caching\\DbDependency\n{\n    if (trim($sql) === '') {\n        throw new \\InvalidArgumentException('DbDependency requires a non-empty sql query.');\n    }\n    return new \\yii\\caching\\DbDependency(['sql' => $sql, 'params' => $params]);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never construct cache dependencies inline with new DbDependency(); route them through a validated factory","Keep the sql key in the same array literal as 'class' => DbDependency::class so it cannot be dropped","Write an integration test that performs one cache->set() per dependency type used by the app"],"tags":["php","yii2","cache","dependency","database","configuration"],"backgroundTag":"missing-required-config","analyzedSha":"66f00d18a29b520f85e8e8f1e32d1e7e7b556cac","analyzedAt":"2026-08-17T05:17:23.470Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}