Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CT-1920] [Bug] Running dbt with state comparison fails if an exposure is disabled #6752

Closed
2 tasks done
rileyschack opened this issue Jan 26, 2023 · 7 comments · Fixed by #6961
Closed
2 tasks done
Labels
bug Something isn't working
Milestone

Comments

@rileyschack
Copy link

rileyschack commented Jan 26, 2023

Is this a new bug in dbt-core?

  • I believe this is a new bug in dbt-core
  • I have searched the existing issues, and I could not find an existing issue for this bug

Current Behavior

State comparison fails (i.e. dbt run -s state:modified -t dev --state prod-target) if an exposure is disabled.

Expected Behavior

State comparison runs should work regardless if an exposure is disabled.

Steps To Reproduce

  1. Used the example dbt BigQuery project generated by dbt init with several modifications:

profiles.yml

config:
  send_anonymous_usage_stats: false

test_project:
  outputs:
    dev:
      type: bigquery
      location: us-east1
      project: sandbox
      dataset: other
      method: oauth
      priority: interactive

models/example/my_exposures.yml

version: 2
exposures:
  - name: my_first_exposure
    type: dashboard
    depends_on:
      - ref("my_second_dbt_model")
    owner:
      email: [email protected]
    url: my_url
    config:
      enabled: false
  1. Ran the following
dbt compile -t dev
cp -a target prod-target
  1. Updated models/example/my_first_dbt_model.sql to trigger a state change, then ran:
dbt run -s +state:modified+ -t dev --state prod-target

Relevant log output

15:02:34  Encountered an error:
Field "disabled" of type Optional[Mapping[str, List[Union[CompiledAnalysisNode, CompiledSingularTestNode, CompiledModelNode, CompiledHookNode, CompiledRPCNode, CompiledSqlNode, CompiledGenericTestNode, CompiledSeedNode, CompiledSnapshotNode, ParsedAnalysisNode, ParsedSingularTestNode, ParsedHookNode, ParsedModelNode, ParsedRPCNode, ParsedSqlNode, ParsedGenericTestNode, ParsedSeedNode, ParsedSnapshotNode, ParsedSourceDefinition]]]] in WritableManifest has invalid value {'exposure.test_project.my_first_exposure': [{'fqn': ['test_project', 'example', 'my_first_exposure'], 'unique_id': 'exposure.test_project.my_first_exposure', 'package_name': 'test_project', 'root_path': '/Users/Riley.Schack/Documents/test-project', 'path': 'example/my_exposures.yml', 'original_file_path': 'models/example/my_exposures.yml', 'name': 'my_first_exposure', 'type': 'dashboard', 'owner': {'email': '[email protected]', 'name': None}, 'resource_type': 'exposure', 'description': '', 'label': None, 'maturity': None, 'meta': {}, 'tags': [], 'config': {'enabled': False}, 'unrendered_config': {'enabled': False}, 'url': 'my_url', 'depends_on': {'macros': [], 'nodes': []}, 'refs': [['my_second_dbt_model']], 'sources': [], 'created_at': 1674745117.410938, 'database': None}]}
15:02:34  Traceback (most recent call last):
  File "<string>", line 93, in from_dict
  File "<string>", line 93, in <dictcomp>
  File "<string>", line 93, in <listcomp>
  File "<string>", line 79, in __unpack_union_WritableManifest_disabled__4a2841212ee94f1c93000693a6d71a60
mashumaro.exceptions.InvalidFieldValue: Field "disabled" of type Union[CompiledAnalysisNode, CompiledSingularTestNode, CompiledModelNode, CompiledHookNode, CompiledRPCNode, CompiledSqlNode, CompiledGenericTestNode, CompiledSeedNode, CompiledSnapshotNode, ParsedAnalysisNode, ParsedSingularTestNode, ParsedHookNode, ParsedModelNode, ParsedRPCNode, ParsedSqlNode, ParsedGenericTestNode, ParsedSeedNode, ParsedSnapshotNode, ParsedSourceDefinition] in WritableManifest has invalid value {'fqn': ['test_project', 'example', 'my_first_exposure'], 'unique_id': 'exposure.test_project.my_first_exposure', 'package_name': 'test_project', 'root_path': '/Users/Riley.Schack/Documents/test-project', 'path': 'example/my_exposures.yml', 'original_file_path': 'models/example/my_exposures.yml', 'name': 'my_first_exposure', 'type': 'dashboard', 'owner': {'email': '[email protected]', 'name': None}, 'resource_type': 'exposure', 'description': '', 'label': None, 'maturity': None, 'meta': {}, 'tags': [], 'config': {'enabled': False}, 'unrendered_config': {'enabled': False}, 'url': 'my_url', 'depends_on': {'macros': [], 'nodes': []}, 'refs': [['my_second_dbt_model']], 'sources': [], 'created_at': 1674745117.410938, 'database': None}

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/Riley.Schack/.pyenv/versions/test-project-env/lib/python3.9/site-packages/dbt/main.py", line 135, in main
    results, succeeded = handle_and_check(args)
  File "/Users/Riley.Schack/.pyenv/versions/test-project-env/lib/python3.9/site-packages/dbt/main.py", line 198, in handle_and_check
    task, res = run_from_args(parsed)
  File "/Users/Riley.Schack/.pyenv/versions/test-project-env/lib/python3.9/site-packages/dbt/main.py", line 225, in run_from_args
    task = parsed.cls.from_args(args=parsed)
  File "/Users/Riley.Schack/.pyenv/versions/test-project-env/lib/python3.9/site-packages/dbt/task/base.py", line 186, in from_args
    return super().from_args(args)
  File "/Users/Riley.Schack/.pyenv/versions/test-project-env/lib/python3.9/site-packages/dbt/task/base.py", line 132, in from_args
    return cls(args, config)
  File "/Users/Riley.Schack/.pyenv/versions/test-project-env/lib/python3.9/site-packages/dbt/task/run.py", line 295, in __init__
    super().__init__(args, config)
  File "/Users/Riley.Schack/.pyenv/versions/test-project-env/lib/python3.9/site-packages/dbt/task/runnable.py", line 118, in __init__
    self.set_previous_state()
  File "/Users/Riley.Schack/.pyenv/versions/test-project-env/lib/python3.9/site-packages/dbt/task/runnable.py", line 122, in set_previous_state
    self.previous_state = PreviousState(
  File "/Users/Riley.Schack/.pyenv/versions/test-project-env/lib/python3.9/site-packages/dbt/contracts/state.py", line 21, in __init__
    self.manifest = WritableManifest.read_and_check_versions(str(manifest_path))
  File "/Users/Riley.Schack/.pyenv/versions/test-project-env/lib/python3.9/site-packages/dbt/contracts/util.py", line 311, in read_and_check_versions
    return cls.from_dict(data)  # type: ignore
  File "<string>", line 95, in from_dict
mashumaro.exceptions.InvalidFieldValue: Field "disabled" of type Optional[Mapping[str, List[Union[CompiledAnalysisNode, CompiledSingularTestNode, CompiledModelNode, CompiledHookNode, CompiledRPCNode, CompiledSqlNode, CompiledGenericTestNode, CompiledSeedNode, CompiledSnapshotNode, ParsedAnalysisNode, ParsedSingularTestNode, ParsedHookNode, ParsedModelNode, ParsedRPCNode, ParsedSqlNode, ParsedGenericTestNode, ParsedSeedNode, ParsedSnapshotNode, ParsedSourceDefinition]]]] in WritableManifest has invalid value {'exposure.test_project.my_first_exposure': [{'fqn': ['test_project', 'example', 'my_first_exposure'], 'unique_id': 'exposure.test_project.my_first_exposure', 'package_name': 'test_project', 'root_path': '/Users/Riley.Schack/Documents/test-project', 'path': 'example/my_exposures.yml', 'original_file_path': 'models/example/my_exposures.yml', 'name': 'my_first_exposure', 'type': 'dashboard', 'owner': {'email': '[email protected]', 'name': None}, 'resource_type': 'exposure', 'description': '', 'label': None, 'maturity': None, 'meta': {}, 'tags': [], 'config': {'enabled': False}, 'unrendered_config': {'enabled': False}, 'url': 'my_url', 'depends_on': {'macros': [], 'nodes': []}, 'refs': [['my_second_dbt_model']], 'sources': [], 'created_at': 1674745117.410938, 'database': None}]}

Environment

- OS: macOS 12.6.1
- Python: 3.9.16
- dbt: 1.3.2

Which database adapter are you using with dbt?

bigquery

Additional Context

Enabled nodes in dev:

❯ dbt ls -t dev                                        
test_project.example.my_first_dbt_model
test_project.example.my_second_dbt_model
test_project.example.not_null_my_first_dbt_model_id
test_project.example.not_null_my_second_dbt_model_id
test_project.example.unique_my_first_dbt_model_id
test_project.example.unique_my_second_dbt_model_id

As soon as I change my_first_exposure to enabled: true, then state comparison works again.

@rileyschack rileyschack added bug Something isn't working triage labels Jan 26, 2023
@github-actions github-actions bot changed the title [Bug] Running dbt with state comparison fails if an exposure is disabled [CT-1920] [Bug] Running dbt with state comparison fails if an exposure is disabled Jan 26, 2023
@dbeatty10
Copy link
Contributor

Hey @rileyschack thanks for "exposing" this situation!

Based on the error message you got using dbt-core==1.3.2, I suspect it's because ParsedExposure is not in the list here.

We just released dbt 1.4 two days ago, and I'm guessing you would still see a similar error since Exposure is not included here.

So this looks like a bug that we'll need to fix, and #6753 will help proactively test for this type of situation in the future.

In the meantime, do you have a workaround that you are using?

@rileyschack
Copy link
Author

@dbeatty10 Thanks for looking into this. My team doesn't have a workaround for this--we were waiting for v1.3 to implement exposures because we needed the enabled configuration for our project. We've put exposures on hold until this is resolved.

Do we have an ETA for the fix? Would it make it into the v1.4.2 release?

@dbeatty10
Copy link
Contributor

Sure thing @rileyschack !

We don't currently have an ETA on this fix. Oftentimes, our bugfixes will only be applied to the next minor version of dbt-core (which is 1.5.0). There are specific scenarios where we will backport a bug fix in a version like 1.4.x:

  1. Is this a regression in a new version of dbt?
  2. Is this a bug related to net-new functionality in this version of dbt?
  3. Is this a narrow bug, with a narrow fix, that's unlikely to cause unintended breakages in other unrelated functionality?
    • This is decided by combination of Product Manager (PM) and Engineering Manager

The reason that Scenario 3 is scoped so tightly is so that we can avoid having a new bugfix accidentally create a new bug and affect folks that were previously fine.

This bug has been pre-existing for multiple versions, so we'd be looking at either Scenario 3 or our next minor version after a fix is merged. I ran this by PM @jtcohen6 and he said it does feel like something that we could include in a v1.4.x patch release 🎉

So we can learn more about how this config is planned to be used, what's effect(s) would you have by not being able to disable exposures?

Here's a super hacky workaround which may (or may not!) work for you in the meantime:

version: 2

exposures:
  # https://github.com/dbt-labs/dbt-core/issues/6752
  # my_first_exposure is "disabled" by commenting out until #6752 resolved
  # - name: my_first_exposure
  #   type: dashboard
  #   owner: [email protected]
  #   depends_on:
  #     - ref("my_second_dbt_model")

  - name: my_second_exposure
    type: analysis
    owner: [email protected]
    depends_on:
      - ref("my_first_dbt_model")

@rileyschack
Copy link
Author

rileyschack commented Jan 27, 2023

@dbeatty10 Thanks for the response--super helpful. I'll keep my fingers crossed for a v1.4.x release since v1.5 is still a few months away 😅

My team has to manage a multi-region dbt project (i.e. each region has a dev/prod target), and we aren't always able to materialize every model in each region (mostly because we don't want to litter each project with null tables). This also means that we have multiple instances of our BI tools (e.g. US, UK, Global) that connect to the different regional BQ projects.

What happens some of the time is that we have a dashboard in 1 region that refs a model that is only enabled in that specific region. This is a key reason we were waiting for the v1.3 release of dbt to start using exposures. A more representative setup would be like this:

version: 2
exposures:
  - name: my_first_exposure
    type: dashboard
    depends_on:
      # this model is only available in prod-uk and dev-uk
      - ref("my_second_dbt_model")
    owner:
      email: [email protected]
    url: my_url
    config:
      enabled: "{{ target.name == 'prod-uk' }}"

@dbeatty10
Copy link
Contributor

Ah, I see what you are hoping to do with conditionally setting enabled based on the target. Agreed that it will require a fix in place to be able to use exposures conditionally like that.

@dbeatty10 dbeatty10 removed the triage label Jan 30, 2023
@emmyoop
Copy link
Member

emmyoop commented Feb 6, 2023

Relates to #6753

@emmyoop
Copy link
Member

emmyoop commented Feb 6, 2023

Will need to think about if we want to backport this with the test from #6753 or not. But that ticket should be done with this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants