Skip to content

Bug fix: the filter of a data stream alias is not always properly removed.#139679

Merged
elasticsearchmachine merged 6 commits intoelastic:mainfrom
gmarouli:fix-data-stream-filtered-alias-clean-up
Dec 17, 2025
Merged

Bug fix: the filter of a data stream alias is not always properly removed.#139679
elasticsearchmachine merged 6 commits intoelastic:mainfrom
gmarouli:fix-data-stream-filtered-alias-clean-up

Conversation

@gmarouli
Copy link
Contributor

A data stream alias that has more than 1 data stream does not handle correctly the removal of a filtered data stream alias. It currently retains the filter even after the alias is removed.

# Create 2 data streams

PUT _data_stream/logs-yyy-default
PUT _data_stream/logs-xxx-default

# Add a filtered alias to one and a simple alias to the other.
POST _aliases
{
  "actions": [
    {
      "add": {
        "index": "logs-yyy-default",
        "alias": "myalias",
        "filter": {
          "term": {
            "type": "mytype"
          }
        }
      }
    },
    {
      "add": {
        "index": "logs-xxx-default",
        "alias": "myalias"
      }
    }
  ]
}

# Remove the filtered alias
POST _aliases
{
  "actions": [
    {
      "remove": {
        "index": "logs-yyy-default",
        "alias": "myalias"
      }
    }
  ]
}

# Add back the alias but WITHOUT filter
POST _aliases
{
  "actions": [
    {
      "add": {
        "index": "logs-yyy-default",
        "alias": "myalias"
       }
    }
  ]
}

The last alias will contain the initial filter while it should not. This PR fixes that.

Furthermore, we edit the update and removal of data streams from an alias to be able to handle orphaned aliases.

@gmarouli gmarouli added >bug :StorageEngine/Data streams Data streams and their lifecycles auto-backport Automatically create backport pull requests when merged branch:9.2 branch:9.1 branch:8.19 labels Dec 17, 2025
@elasticsearchmachine
Copy link
Collaborator

Pinging @elastic/es-data-management (Team:Data Management)

@elasticsearchmachine
Copy link
Collaborator

Hi @gmarouli, I've created a changelog YAML for you.

@lukewhiting lukewhiting requested a review from Copilot December 17, 2025 10:32
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a bug where filtered data stream aliases were not properly removed when an alias was deleted and then re-added without a filter. The filter from the original alias would persist incorrectly. Additionally, the PR adds handling for orphaned alias filters (filters that exist for data streams no longer in the alias).

Key Changes:

  • Modified DataStreamAlias.update() and DataStreamAlias.removeDataStream() to properly clean up filters when removing data streams or updating aliases without filters
  • Added capability flag fix_filtered_data_stream_alias_removal to track this fix
  • Added comprehensive test coverage for filtered alias removal and orphaned filter cleanup

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
DataStreamAlias.java Core logic fix to properly remove filters when updating or removing data streams from aliases
DataStreamAliasTests.java Added unit tests for filtered data stream removal and orphaned filter cleanup
RestIndicesAliasesAction.java Added capability flag to indicate the bug fix is available
140_data_stream_aliases.yml Added integration test verifying filtered alias removal behavior
139679.yaml Changelog entry documenting the bug fix

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

if (filterAsMap != null || dataStreamToFilterMap.containsKey(dataStream)) {
CompressedXContent previousFilter = dataStreamToFilterMap.get(dataStream);
if (previousFilter == null) {
if (previousFilter == null || filterAsMap == null) {
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition previousFilter == null || filterAsMap == null could be clearer. Consider splitting this into separate conditions with explicit comments explaining when each case occurs (adding a new filter vs. removing an existing filter).

Copilot uses AI. Check for mistakes.
Copy link
Contributor

@lukewhiting lukewhiting left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me 👍🏻 Thanks for sorting this!

@gmarouli gmarouli added the auto-merge-without-approval Automatically merge pull request when CI checks pass (NB doesn't wait for reviews!) label Dec 17, 2025
@elasticsearchmachine elasticsearchmachine merged commit 7e84a3c into elastic:main Dec 17, 2025
35 checks passed
@gmarouli gmarouli deleted the fix-data-stream-filtered-alias-clean-up branch December 17, 2025 13:56
@elasticsearchmachine
Copy link
Collaborator

💚 Backport successful

Status Branch Result
9.1
9.2
8.19
gmarouli added a commit to gmarouli/elasticsearch that referenced this pull request Dec 17, 2025
…oved. (elastic#139679)

A data stream alias that has more than 1 data stream does not handle
correctly the removal of a filtered data stream alias. It currently
retains the filter even after the alias is removed.

```
# Create 2 data streams

PUT _data_stream/logs-yyy-default
PUT _data_stream/logs-xxx-default

# Add a filtered alias to one and a simple alias to the other.
POST _aliases
{
  "actions": [
    {
      "add": {
        "index": "logs-yyy-default",
        "alias": "myalias",
        "filter": {
          "term": {
            "type": "mytype"
          }
        }
      }
    },
    {
      "add": {
        "index": "logs-xxx-default",
        "alias": "myalias"
      }
    }
  ]
}

# Remove the filtered alias
POST _aliases
{
  "actions": [
    {
      "remove": {
        "index": "logs-yyy-default",
        "alias": "myalias"
      }
    }
  ]
}

# Add back the alias but WITHOUT filter
POST _aliases
{
  "actions": [
    {
      "add": {
        "index": "logs-yyy-default",
        "alias": "myalias"
       }
    }
  ]
}
```

The last alias will contain the initial filter while it should not. This
PR fixes that.

Furthermore, we edit the update and removal of data streams from an
alias to be able to handle orphaned aliases.
gmarouli added a commit to gmarouli/elasticsearch that referenced this pull request Dec 17, 2025
…oved. (elastic#139679)

A data stream alias that has more than 1 data stream does not handle
correctly the removal of a filtered data stream alias. It currently
retains the filter even after the alias is removed.

```
# Create 2 data streams

PUT _data_stream/logs-yyy-default
PUT _data_stream/logs-xxx-default

# Add a filtered alias to one and a simple alias to the other.
POST _aliases
{
  "actions": [
    {
      "add": {
        "index": "logs-yyy-default",
        "alias": "myalias",
        "filter": {
          "term": {
            "type": "mytype"
          }
        }
      }
    },
    {
      "add": {
        "index": "logs-xxx-default",
        "alias": "myalias"
      }
    }
  ]
}

# Remove the filtered alias
POST _aliases
{
  "actions": [
    {
      "remove": {
        "index": "logs-yyy-default",
        "alias": "myalias"
      }
    }
  ]
}

# Add back the alias but WITHOUT filter
POST _aliases
{
  "actions": [
    {
      "add": {
        "index": "logs-yyy-default",
        "alias": "myalias"
       }
    }
  ]
}
```

The last alias will contain the initial filter while it should not. This
PR fixes that.

Furthermore, we edit the update and removal of data streams from an
alias to be able to handle orphaned aliases.
elasticsearchmachine pushed a commit that referenced this pull request Dec 17, 2025
…oved. (#139679) (#139688)

A data stream alias that has more than 1 data stream does not handle
correctly the removal of a filtered data stream alias. It currently
retains the filter even after the alias is removed.

```
# Create 2 data streams

PUT _data_stream/logs-yyy-default
PUT _data_stream/logs-xxx-default

# Add a filtered alias to one and a simple alias to the other.
POST _aliases
{
  "actions": [
    {
      "add": {
        "index": "logs-yyy-default",
        "alias": "myalias",
        "filter": {
          "term": {
            "type": "mytype"
          }
        }
      }
    },
    {
      "add": {
        "index": "logs-xxx-default",
        "alias": "myalias"
      }
    }
  ]
}

# Remove the filtered alias
POST _aliases
{
  "actions": [
    {
      "remove": {
        "index": "logs-yyy-default",
        "alias": "myalias"
      }
    }
  ]
}

# Add back the alias but WITHOUT filter
POST _aliases
{
  "actions": [
    {
      "add": {
        "index": "logs-yyy-default",
        "alias": "myalias"
       }
    }
  ]
}
```

The last alias will contain the initial filter while it should not. This
PR fixes that.

Furthermore, we edit the update and removal of data streams from an
alias to be able to handle orphaned aliases.
elasticsearchmachine pushed a commit that referenced this pull request Dec 17, 2025
…oved. (#139679) (#139689)

A data stream alias that has more than 1 data stream does not handle
correctly the removal of a filtered data stream alias. It currently
retains the filter even after the alias is removed.

```
# Create 2 data streams

PUT _data_stream/logs-yyy-default
PUT _data_stream/logs-xxx-default

# Add a filtered alias to one and a simple alias to the other.
POST _aliases
{
  "actions": [
    {
      "add": {
        "index": "logs-yyy-default",
        "alias": "myalias",
        "filter": {
          "term": {
            "type": "mytype"
          }
        }
      }
    },
    {
      "add": {
        "index": "logs-xxx-default",
        "alias": "myalias"
      }
    }
  ]
}

# Remove the filtered alias
POST _aliases
{
  "actions": [
    {
      "remove": {
        "index": "logs-yyy-default",
        "alias": "myalias"
      }
    }
  ]
}

# Add back the alias but WITHOUT filter
POST _aliases
{
  "actions": [
    {
      "add": {
        "index": "logs-yyy-default",
        "alias": "myalias"
       }
    }
  ]
}
```

The last alias will contain the initial filter while it should not. This
PR fixes that.

Furthermore, we edit the update and removal of data streams from an
alias to be able to handle orphaned aliases.
elasticsearchmachine pushed a commit that referenced this pull request Dec 17, 2025
…oved. (#139679) (#139691)

A data stream alias that has more than 1 data stream does not handle
correctly the removal of a filtered data stream alias. It currently
retains the filter even after the alias is removed.

```
# Create 2 data streams

PUT _data_stream/logs-yyy-default
PUT _data_stream/logs-xxx-default

# Add a filtered alias to one and a simple alias to the other.
POST _aliases
{
  "actions": [
    {
      "add": {
        "index": "logs-yyy-default",
        "alias": "myalias",
        "filter": {
          "term": {
            "type": "mytype"
          }
        }
      }
    },
    {
      "add": {
        "index": "logs-xxx-default",
        "alias": "myalias"
      }
    }
  ]
}

# Remove the filtered alias
POST _aliases
{
  "actions": [
    {
      "remove": {
        "index": "logs-yyy-default",
        "alias": "myalias"
      }
    }
  ]
}

# Add back the alias but WITHOUT filter
POST _aliases
{
  "actions": [
    {
      "add": {
        "index": "logs-yyy-default",
        "alias": "myalias"
       }
    }
  ]
}
```

The last alias will contain the initial filter while it should not. This
PR fixes that.

Furthermore, we edit the update and removal of data streams from an
alias to be able to handle orphaned aliases.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auto-backport Automatically create backport pull requests when merged auto-merge-without-approval Automatically merge pull request when CI checks pass (NB doesn't wait for reviews!) >bug :StorageEngine/Data streams Data streams and their lifecycles Team:Data Management (obsolete) DO NOT USE. This team no longer exists. v8.19.10 v9.1.10 v9.2.4 v9.3.0

4 participants