Skip to content

fix(config): reject FSDP strategies that transformers' FSDP2 default cannot run, and warn about two ignored knobs - #990

Closed
cemililik wants to merge 1 commit into
developmentfrom
fix/fsdp-reject-fsdp1-only-strategies
Closed

cemililik wants to merge 1 commit into
developmentfrom
fix/fsdp-reject-fsdp1-only-strategies

Conversation

@cemililik

@cemililik cemililik commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

distributed.fsdp_strategy accepted no_shard and hybrid_shard (the latter described as the multi-node option). transformers 5.10 made FSDP2 the default, and FSDP2 raises `fsdp=hybrid_shard` is only available with FSDP1 when TrainingArguments is built. A config with either value passed --dry-run and then exited 2 after the model was loaded. It is now refused when the config loads (exit 1). Two more knobs that FSDP2 silently ignores now log a warning.

Related issues

Refs #104 — the config-time rejection and the "no knob is silently dead" half. Moving to the FSDP2 form (fsdp=True plus an explicit fsdp_config) is deliberately not done here; the string form is deprecated in transformers and slated for removal in v5.20, so that migration remains open on the issue.

Merge order: the documentation says "transformers 5.10+, which ForgeLM requires". That is true once #989 (the transformers floor) is merged; please merge it first, or this one will briefly overstate the requirement.

Changes

  • forgelm/config.py: fsdp_strategy is Literal["full_shard", "shard_grad_op"]. The three field descriptions say what FSDP2 ignores. All edits are in place, so config.py (zero line headroom on the module-size ratchet) is unchanged in size.
  • forgelm/cli/_config_load.py + forgelm/cli/_dispatch.py: _warn_inert_fsdp_options() logs a warning when fsdp_auto_wrap: false or fsdp_backward_prefetch: backward_post is set. It lives in the CLI layer for the same budget reason.
  • Docs (English and Turkish): the distributed-training reference, the configuration references, the distributed training and configuration user-manual pages, config_template.yaml.

Checked against transformers

Real TrainingArguments, string fsdp, on 5.10.1 and 5.13.0:

fsdp_strategy result
full_shard, shard_grad_op built; reshard_after_forward is True / False; state_dict_type honoured
no_shard, hybrid_shard ValueError ("only available with FSDP1")

With fsdp_auto_wrap: false or backward_post the plugin is identical to the default one (always TRANSFORMER_BASED_WRAP, no prefetch argument), which is why those two are warnings and not errors: they are accepted, they change nothing.

Type

  • Bug fix

Testing

  • tests/test_distributed.py:
    • both strategies are rejected by the schema, and a --dry-run of such a config exits EXIT_CONFIG_ERROR;
    • all 32 accepted variants (strategy × auto-wrap × offload × prefetch × state-dict) build real TrainingArguments through ForgeTrainer._apply_distributed_config, so what the schema accepts can no longer be something TrainingArguments refuses;
    • the warning fires for each inert setting, is silent for defaults, DeepSpeed and no distributed block, and a real --dry-run reaches it.
  • Mutation checks: widening the Literal again fails four tests; removing the warning call from main() fails the dry-run test.
  • The full CLAUDE.md gauntlet from a clean worktree of this branch: exit 0.

Checklist

  • English and Turkish mirrors updated together
  • CHANGELOG entry under [Unreleased]
  • Tests added

🤖 Generated with Claude Code

Summary by Sourcery

Validate FSDP settings against transformers FSDP2 and surface configuration options that no longer have an effect.

Bug Fixes:

  • Reject FSDP strategies unsupported by transformers' FSDP2 during configuration validation instead of allowing them to fail later during trainer construction.
  • Warn when FSDP options are accepted but ignored by FSDP2.

Enhancements:

  • Align FSDP configuration descriptions and supported strategy documentation with transformers 5.10+ behavior.

Documentation:

  • Update English and Turkish FSDP references, user manuals, and the configuration template to document supported strategies and ignored options.

Tests:

  • Add coverage for config-time rejection, exit codes, all accepted FSDP option combinations, and warnings for inert settings.

Chores:

  • Record the FSDP compatibility fix in the unreleased changelog.

…cannot run, and warn about two ignored knobs

distributed.fsdp_strategy accepted no_shard and hybrid_shard (the latter described as the multi-node option). transformers
5.10 made FSDP2 the default, and FSDP2 raises "fsdp=hybrid_shard is only available with FSDP1" when TrainingArguments is
built, so such a config passed --dry-run and then exited 2 after the model was loaded. The strategy is now a Literal of
full_shard and shard_grad_op, so the config is refused at load time with exit 1.

fsdp_auto_wrap: false and fsdp_backward_prefetch: backward_post are still accepted but change nothing under FSDP2 (the
plugin always applies the transformer-layer wrap policy and takes no prefetch policy; checked against TrainingArguments on
5.10.1 and 5.13.0). The CLI now logs a warning when either is set away from its default, and the field descriptions,
reference pages, user manuals and config_template.yaml say so. The warning lives in cli/_config_load.py because
config.py and trainer.py are at their deferred-split line budgets.

A new test builds TrainingArguments for all 32 accepted variants through ForgeTrainer._apply_distributed_config, so a
config the schema accepts can no longer be one TrainingArguments refuses. Moving to the FSDP2 form (fsdp=True plus an
explicit fsdp_config) is not part of this change.

Depends on the transformers floor moving to 5.10.1 (#109); the docs say "transformers 5.10+, which ForgeLM requires".

Refs #104

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@sourcery-ai

sourcery-ai Bot commented Oct 18, 2026

Copy link
Copy Markdown

Sorry @cemililik, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 13 hours and 5 minutes by commenting @sourcery-ai review. Upgrade to get a review now.

@coderabbitai

coderabbitai Bot commented Oct 18, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

Next included review available in 8 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 3 included reviews currently available. Your 48 included PR review attempts over the past 7 days set your current allowance at 3 reviews per hour.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: e8dd6025-da3b-4ed3-88f2-3112e1ac6609
📥 Commits

Reviewing files that changed from the base of the PR and between 56b4f0d and 4d73a35.

📒 Files selected for processing: 14
  • CHANGELOG.md
  • config_template.yaml
  • docs/reference/configuration-tr.md
  • docs/reference/configuration.md
  • docs/reference/distributed_training-tr.md
  • docs/reference/distributed_training.md
  • docs/usermanuals/en/reference/configuration.md
  • docs/usermanuals/en/training/distributed.md
  • docs/usermanuals/tr/reference/configuration.md
  • docs/usermanuals/tr/training/distributed.md
  • forgelm/cli/_config_load.py
  • forgelm/cli/_dispatch.py
  • forgelm/config.py
  • tests/test_distributed.py
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@sourcery-ai

sourcery-ai Bot commented Oct 18, 2026

Copy link
Copy Markdown

Reviewer's Guide

This PR makes FSDP2 compatibility explicit by rejecting the unsupported no_shard and hybrid_shard strategies at config load time, warning when two accepted FSDP settings are ignored, updating English/Turkish documentation and templates, and adding comprehensive validation, integration, and CLI warning tests.

Sequence diagram for FSDP configuration loading and dispatch

sequenceDiagram
    participant CLI
    participant ConfigLoader
    participant Validator
    participant WarningChecker
    participant Dispatcher
    participant Transformers

    CLI->>ConfigLoader: _load_config_or_exit()
    ConfigLoader->>Validator: Validate DistributedConfig
    alt unsupported fsdp_strategy
        Validator-->>ConfigLoader: Validation error
        ConfigLoader-->>CLI: EXIT_CONFIG_ERROR
    else supported fsdp_strategy
        ConfigLoader-->>CLI: config
        CLI->>WarningChecker: _warn_inert_fsdp_options(config)
        alt inert option configured
            WarningChecker-->>CLI: logger.warning()
        end
        CLI->>Dispatcher: Dispatch training or dry-run
        Dispatcher->>Transformers: Build TrainingArguments
        Transformers-->>Dispatcher: FSDP2-compatible arguments
    end
Loading

Flow diagram for FSDP2 configuration validation and warnings

flowchart TD
    A[Load configuration] --> B{fsdp_strategy supported?}
    B -->|no_shard or hybrid_shard| C[Reject configuration with EXIT_CONFIG_ERROR]
    B -->|full_shard or shard_grad_op| D[Apply offline flag]
    D --> E{FSDP strategy enabled?}
    E -->|No| F[Continue dispatch]
    E -->|Yes| G{Inert option set?}
    G -->|fsdp_auto_wrap=false| H[Log warning]
    G -->|fsdp_backward_prefetch=backward_post| I[Log warning]
    G -->|Neither| F
    H --> F
    I --> F
Loading

File-Level Changes

Change Details Files
Restrict FSDP strategy configuration to the two strategies supported by transformers FSDP2, causing invalid values to fail during config validation.
  • Narrowed the schema literal to full_shard and shard_grad_op.
  • Updated field descriptions and configuration templates to document the rejection and FSDP2 behavior.
forgelm/config.py
config_template.yaml
Surface FSDP2 configuration options that are accepted but have no runtime effect.
  • Added CLI-layer warnings for fsdp_auto_wrap: false and fsdp_backward_prefetch: backward_post.
  • Invoke the warning check immediately after configuration loading so dry runs and normal commands report inert settings.
  • Keep warnings limited to FSDP configurations.
forgelm/cli/_config_load.py
forgelm/cli/_dispatch.py
Align user-facing documentation and release notes with the FSDP2 compatibility changes.
  • Updated English and Turkish distributed-training and configuration references.
  • Documented the rejected strategies, ignored knobs, warning behavior, and supported values.
  • Added an Unreleased changelog entry.
docs/reference/configuration.md
docs/reference/configuration-tr.md
docs/reference/distributed_training.md
docs/reference/distributed_training-tr.md
docs/usermanuals/en/reference/configuration.md
docs/usermanuals/en/training/distributed.md
docs/usermanuals/tr/reference/configuration.md
docs/usermanuals/tr/training/distributed.md
CHANGELOG.md
Add coverage for schema rejection, CLI exit behavior, accepted FSDP combinations, and inert-option warnings.
  • Verify no_shard and hybrid_shard fail validation and dry-run with the config-error exit code.
  • Exercise all 32 accepted FSDP option combinations through real TrainingArguments construction.
  • Verify warnings for each inert setting, silence for defaults and non-FSDP modes, and warning propagation through dry-run.
tests/test_distributed.py

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@cemililik

Copy link
Copy Markdown
Collaborator Author

Superseded by #999: the wave-0 fixes are combined by theme into five pull requests to cut the review load. This branch's commits are included there unchanged apart from the CHANGELOG.md merge; the branch stays on the remote.

@cemililik cemililik closed this Oct 18, 2026
cemililik added a commit that referenced this pull request Oct 18, 2026
…n.enforce, transformers CVE floor, FSDP strategies, purge output dir (#999)

## Summary

Six code fixes combined into one pull request, replacing #984, #985,
#987, #989, #990 and #992 (to be closed as superseded). Each fixes a
case where the code failed, or a documented option did nothing, without
saying so. Each was mutation-checked on its own; together they pass the
full gauntlet.

## Related issues

Refs #103, #95, #92, #98, #109, #104, #102. Not closed by this change:
the top-of-range problems named in #109 (`warmup_ratio` on transformers
5.15+, the string `fsdp` form removed in 5.20), the FSDP2 migration
(#104), and reading `training.output_dir` for the purge memorisation
check (#102).

## Changes

| # | Fix | Where |
|---|---|---|
| #984 | `training.rope_scaling` crashed every model load on
transformers 5 (`KeyError: 'rope_type'`, or `rope_theta` lost). The
requested keys are merged **over** the model's `rope_parameters` and the
finished config is loaded; `sliding_window_attention` travels in the
same config object. | `forgelm/model.py` |
| #985 | The CLI sets `HF_HUB_DISABLE_TELEMETRY=1` (via `setdefault`)
before `huggingface_hub` is imported, so TRL's trainer no longer sends
Hugging Face's anonymous usage ping the privacy page says does not
exist. Library use is not covered; the air-gap page says so. |
`cli/_config_load.py`, `cli/_dispatch.py` |
| #987 | `retention.enforce` was documented as a gate (`warn_on_excess`,
`block_on_excess` → `EXIT_EVAL_FAILURE`) but no command reads it. Docs,
field description, both wizards say it is reserved; the CLI warns when a
config sets either of the last two. | `config.py` (in place),
`cli/_config_load.py`, `wizard/_collectors.py` |
| #989 | `transformers>=5.3.0` was called the CVE floor but admitted
CVE-2026-5241 and CVE-2026-9856 (a crafted `chat_template` name writes
outside the save directory). Floor is now `>=5.10.1` (5.10.0 is yanked),
`huggingface_hub>=1.5.0`, the nightly floor job pins both, and tests
keep it from drifting. | `pyproject.toml`, `nightly.yml`, `tests/` |
| #990 | `fsdp_strategy: no_shard` / `hybrid_shard` passed `--dry-run`
and exited 2 after the model loaded (FSDP2 rejects them). They are now
rejected when the config loads (exit 1), and two knobs FSDP2 ignores
(`fsdp_auto_wrap: false`, `backward_post`) log a warning. | `config.py`
(in place), `cli/_config_load.py` |
| #992 | `forgelm purge --row-id` without `--output-dir` silently
pointed the memorisation check at the corpus directory. It now warns and
names the path. The purge module's line budget is raised by 8 with a
`budget_history` note (the project's documented option). |
`cli/subcommands/_purge.py`, `tools/check_module_size.py` |

`config.py` (0 lines of headroom on the module-size ratchet) and
`trainer.py` change only by in-place string edits; new warnings live in
`cli/_config_load.py`.

### Merge-conflict handling

The six branches touched `CHANGELOG.md`, `tests/test_cli.py` (two
appended test classes) and the import line in `cli/_dispatch.py`; all
three were resolved by keeping both sides (the import line now imports
`_disable_hub_telemetry` and `_warn_inert_fsdp_options`). The affected
test modules pass together (621 tests).

## Type

- [x] Bug fix
- [x] Dependency

## Testing

- The full `CLAUDE.md` gauntlet from a clean worktree of this branch:
exit 0.
- Per-fix tests as in the original pull requests, including: a real tiny
Llama on CPU for `rope_scaling` (linear, dynamic, yarn); the traversal
reproduction (**fails on transformers 5.3.0**, passes on 5.10.1); all 32
accepted FSDP variants building real `TrainingArguments`.
- transformers-facing test modules pass on a 5.10.1 / `huggingface_hub`
1.5.0 overlay (443 tests). The nightly minimum-versions job runs on its
schedule after merge; I did not dispatch it.

## Checklist

- [x] English and Turkish mirrors updated together
- [x] CHANGELOG entries under `[Unreleased]`
- [x] Tests added

🤖 Generated with [Claude Code](https://claude.com/claude-code)

## Summary by Sourcery

Harden CLI behavior and dependency compatibility across model loading,
privacy, retention, distributed training, and purge workflows.

Bug Fixes:
- Restore Transformers 5 compatibility for RoPE scaling and
sliding-window model configuration.
- Disable Hugging Face Hub telemetry by default for CLI runs while
preserving explicit operator opt-in.
- Warn when reserved retention enforcement modes are configured instead
of implying unsupported enforcement behavior.
- Reject unsupported FSDP1-only strategies during configuration and warn
about FSDP2 options that have no effect.
- Warn when purge uses the corpus directory as its implicit output
directory and clarify the memorisation-check scope.

Enhancements:
- Document the actual retention, FSDP, telemetry, and purge behavior in
English and Turkish user-facing documentation.

Build:
- Raise the minimum runtime dependencies to transformers>=5.10.1 and
huggingface_hub>=1.5.0 to address relevant security advisories.
- Update the nightly minimum-version job and packaging checks to enforce
the new dependency floors.

Tests:
- Add coverage for telemetry initialization, reserved retention
warnings, FSDP validation, purge output-directory warnings, Transformers
5 RoPE handling, and chat-template path traversal protection.

Chores:
- Increase the purge module size budget for the new output-directory
warning.

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant