instructure/canvas-lms · warning
DataFixup::MoveFeatureFlagsToSettings => unable to handle…
Error message
DataFixup::MoveFeatureFlagsToSettings => unable to handle override state for context #{context.asset_string} of feature #{override.id} with state #{override.state} What it means
A warning logged by the DataFixup::MoveFeatureFlagsToSettings data fixup when it encounters a FeatureFlagOverride whose state is not one of 'on', 'off', or 'locked' that it can map to a value. The fixup cannot translate the override into the new settings storage, so it logs and skips that override rather than migrating it.
Solutions
- Inspect the offending rows: SELECT * FROM feature_flag_overrides WHERE state NOT IN ('on','off','locked'); and decide the correct value per row.
- Normalize the unexpected states to 'on'/'off'/'locked' (based on the feature's current behavior) and re-run the fixup.
- If the state is genuinely meaningless (deleted feature/context), delete the orphan override row, then re-run the fixup.
- Extend the fixup's case/when mapping if the new settings schema has a representation for that state.
Example fix
// before
UPDATE feature_flag_overrides SET state = 'on' WHERE state = 'allowed';
// after
UPDATE feature_flag_overrides SET state = 'on' WHERE state NOT IN ('on','off','locked');
-- then re-run DataFixup::MoveFeatureFlagsToSettings.run Defensive patterns
Strategy: validation
Validate before calling
bad = FeatureFlagOverride.where.not(state: %w[on off locked])
bad.find_each do |o|
Rails.logger.warn("un-migratable override: feature=#{o.feature} state=#{o.state}")
end Type guard
def valid_override_state?(state) %w[on off locked].include?(state) end
Try / catch
FeatureFlagOverride.find_each do |override|
unless %w[on off locked].include?(override.state)
next # or normalize before running the fixup
end
end Prevention
- Audit feature_flag_overrides for non-standard state values before running fixups
- Only mutate override state through AR validations/enums, never raw SQL
- Run fixups in staging against a production snapshot first
- Track skipped overrides (asset_string list) to reconcile after the run
When it happens
Trigger: Running the move_feature_flags_to_settings fixup over feature_flag_overrides rows containing a state value outside {'locked','on','off'} — typically stale, corrupted, or legacy rows written before the state enum was normalized.
Common situations: Long-lived production databases with overrides from old Canvas versions whose state strings were renamed or removed; manual DB edits or partial migrations leaving unexpected state values; running the fixup against a restored/partial dataset.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Cannot validate existence for resource type: #
- Canvas Career permission overrides failed: #
- Couldn't convert QTI 1.2 to 2.1, see error log: #
- course hasn't been converted
- Course not found
AI-assisted analysis of instructure/canvas-lms@1c9f0bb801 (2026-09-15).
Data as JSON: /api/errors/6a505989090c8495.
Report an issue: GitHub.
Appendix: source
Thrown at lib/data_fixup/move_feature_flags_to_settings.rb:81
context.feature_flags.detect { |ff| ff.feature == feature_flag_name.to_s }
else
context.feature_flags.find_by(feature: feature_flag_name.to_s)
end
override_value = nil
locked = true
if override
case override.state
when "allowed"
# no op
when "allowed_on"
override_value = true
locked = false
when "on"
override_value = true
when "off"
override_value = false
else
Rails.logger.warn("DataFixup::MoveFeatureFlagsToSettings => unable to handle override state for context " \
"#{context.asset_string} of feature #{override.id} with state #{override.state}")
end
end
unless override_value.nil?
if context.is_a?(Account)
context.settings[setting_name] = inherited ? { locked:, value: override_value } : override_value
else
context.settings_frd[setting_name] = override_value
end
context.save!
end
end
private_class_method :figure_setting_from_override
end
View on GitHub (pinned to 1c9f0bb801)