dbt-core: [CT-1436] Treat warnings as errors for specific events, based on user configuration
Today, --warn-error is a simple on/off switch that turns all warnings into errors. We’ve gotten multiple requests (https://github.com/dbt-labs/dbt-core/issues/4383, https://github.com/dbt-labs/dbt-core/issues/6080) from users who want finer-grained control for raising errors on specific types of warnings.
We should allow users to configure exactly which event classes they want to raise as exceptions instead of warnings. This will be enabled by https://github.com/dbt-labs/dbt-core/pull/6064, which will turn all warn_or_error call sites into structured events.
Where should this configuration live? It feels like “runtime” config, rather than something that goes in project code. But it might be awkward to pass as a CLI flag or env var. The best places feels like the “user config” which currently lives in profiles.yml.
config:
warn_error: true # all of them
config:
warn_error_events: # scoped down to specific events
- NoNodesForSelectionCriteria
- UnusedResourceConfigPath
def warn_or_error(event, node):
# pseudo code!
if flags.WARN_ERROR or type(event) in flags.WARN_ERROR_EVENTS:
from dbt.exceptions import raise_compiler_error
raise_compiler_error(scrub_secrets(event.info.msg, env_secrets()), node)
else:
fire_event(event)
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 17 (15 by maintainers)
A functionally similar configuration syntax was recently proposed in the dbt should know more about semantic information issue. It turns out that entity definitions also need to provide an overall true/false option, plus some additional include/exclude modifications.
Implementing the same configuration syntax for
warn_errorwould need some custom validation (expecting valid exception class names, not column names), but would have the benefit of a consistent experience with what’s being proposed for entities. Below are a few examples of the syntax applied to thewarn_errorconfig:c’est comme ça
We could support “all” as an alias:
Looking into the code I would say we actually have three types of warnings: deprecations, bad configs and tests + source freshness checks. Both deprecations and configs are already implemented differently since they are both utilizing warn_or_error where tests and source configs are setting the result status based on if the
warn-errorflag is set but do not usewarn_or_error.warn-errorflag could just get deprecated at some point. The problem here would be clearly defining what wins (or throwing an error when old and new flags are used within the same project)Looking at other compilers: C# covers its bases with
GCC actually does something similar where you can
Making a note to not lose it:
mypydoes something similar with error codes (disable_error_codes and enable_error_codes) but is not exactly the same as what we’re trying to do. The interesting thing is that it’s two separate configs and they also make the executive decision that(enable_error_codes)... will override disabled error codes from the disable_error_code option. So if both are filled it’s well documented what wins while also having explicit fields.(summary from follow-up convo w @MichelleArk)
We can’t have one CLI flag that’s both a boolean and also a dict.
argparseisn’t happy with that,clickisn’t happy with that, and if we’re being honest with ourselves, we shouldn’t be too happy about doing it either.Let’s make a new config (+ flag/env var), call it
warn_error_options, data structure is always a dictionary that looks like{"include": str | list, "exclude": list}. This will be distinct from and mutually exclusive with the existing boolean config/flag/var namedwarn_error. Note: This means it would not be possible to supplywarn_error_optionsinUserConfigand override with plain old--warn-errorin env var / CLI — you have to override like with like.Is it a bit ugly? Yes. But it’s a single variable, you only need to set it once, you can pop it in a yaml/json validator first, and ultimately, this is a capability intended for fairly advanced users. More important that it’s possible on the CLI, than it being ergonomic & delightful. Ultimately, we should also move
UserConfigsomewhere else (#6266) such that dbt Cloud users can actually make use of it, without needing to modifyprofiles.ymldirectly.These two are still identical:
Theoretically these should also be equivalent:
Up to us if we eventually (dbt v2) deprecate the existing
--warn-errorconfig. It’s a lot sugarier for sure. No deprecation warning for now.& the good old fashioned
--warn-errorbool will also want to keep working, with the same effect as “include all”:That could work nicely! One edge case I can think of would be for entity definitions where a column name is actually called ‘all’ - how would dbt disambiguate between a column named ‘all’ vs ‘include all columns’? I don’t think this is an issue for the
warn_errorconfiguration since dbt-core provides the exception names.One way to disambiguate between a column named ‘all’ vs the directive to include all column names without complex validation would be based on the presence of ‘all’ as a string vs a list item. For example:
vs
One thing to check during implementation: The spec looks great as yaml, but dbt Cloud users don’t have the ability to write/edit
profiles.yml, which is whereUserConfiglives right now.It will need to be possible to pass these data structures in as an env var (
DBT_WARN_ERROR) or CLI flag (--warn-error) as well (even if it’s super ugly to look at).Something like:
An observation - it appears yml doesn’t support non-quoted special characters such as
*. See link here and explanation from Stack Overflow.This implies that the syntax will be the slightly less clean:
My understanding of Nate’s proposal:
warn_erroris still a simple on/off, for all non-ignored warningsThe appeal of that approach is it’s more in keeping with the standard practice of other compilers. The downside is losing some of the flexibility that the more-complex configuration (proposed in this issue) would enable.
As part of this work, we should remove
warn_or_errorentirely to make thewarn_errorconfig work for all warnings, not just a subset.This will involve changing all callsites for
warn_or_errortofire_event.dbt-snowflakeuseswarn_or_errorin connections.py.Note: This could be a breaking change for community adapters if they use
warn_or_error.