Skip to content

Function App: --slot-settings parameter fails to update existing Function App slot settings #32290

@jcassanji-southworks

Description

@jcassanji-southworks

Bug: --slot-settings parameter fails to update existing Function App slot settings

Summary

The az functionapp config appsettings set --slot-settings command fails to update existing slot settings when using any input format, while the --settings parameter works correctly for the same operation.

Azure CLI Version

azure-cli                         2.78.0

Environment

  • OS: Windows
  • Shell: PowerShell

Expected Behavior

Click to expand Expected Behavior details

When using the --slot-settings parameter with Azure CLI's az functionapp config appsettings set command, the following behaviors should work consistently:

1. Inline Parameter Format

az functionapp config appsettings set --resource-group myRG --name myFunctionApp --slot mySlot --slot-settings "SETTING_NAME=value"

Expected Result: The setting should be created/updated with the specified value AND marked as a slot-specific setting (slotSetting: true).

2. Updating Existing Slot Settings - Key Issue

When a slot setting already exists with any value:

# Initial setting (works)
az functionapp config appsettings set --slot mySlot --slot-settings "EXISTING_SETTING=initial-value"

# Update attempts (currently failing)
az functionapp config appsettings set --slot mySlot --slot-settings "EXISTING_SETTING=updated-value"

Expected Result:

  • The setting value should be updated from "initial-value" to "updated-value"
  • The setting should remain as a slot-specific setting (slotSetting: true)
  • The change should only affect the specified slot, not the production slot

Current Actual Result: The value remains unchanged at "initial-value"

3. JSON File Input - Array Format

az functionapp config appsettings set --resource-group myRG --name myFunctionApp --slot mySlot --slot-settings @settings.json

Where settings.json contains:

[
  {
    "name": "EXISTING_SETTING",
    "slotSetting": true,
    "value": "new-value-from-array"
  }
]

Expected Result: Existing slot settings should be updated with the new values from the JSON file.

4. JSON File Input - Object Format

az functionapp config appsettings set --resource-group myRG --name myFunctionApp --slot mySlot --slot-settings @settings.json

Where settings.json contains:

{
  "EXISTING_SETTING": "new-value-from-object"
}

Expected Result: Existing slot settings should be updated with the new values, and new settings should be automatically marked as slot-specific.

Actual Behavior

Click to expand Actual Behavior details
  • Using --slot-settings with any format does not update existing slot settings values
  • The slot configuration (slotSetting: true) is maintained, but the actual values remain unchanged
  • Using --settings incorrectly updates the same settings but does change the values (though it marks them as regular settings instead of slot settings)

Steps to Reproduce

Click to expand Reproduction Steps
  1. Create a Function App with a deployment slot

  2. Set an initial slot setting:

    az functionapp config appsettings set --resource-group myRG --name myFunctionApp --slot mySlot --slot-settings "TEST_SETTING=initial-value"
  3. Verify the setting was created:

    az functionapp config appsettings list --resource-group myRG --name myFunctionApp --slot mySlot --query "[?name=='TEST_SETTING']"

    Result: Shows {"name": "TEST_SETTING", "slotSetting": true, "value": "initial-value"}

  4. Try to update using inline format:

    az functionapp config appsettings set --resource-group myRG --name myFunctionApp --slot mySlot --slot-settings "TEST_SETTING=updated-value"
  5. Verify the value:

    az functionapp config appsettings list --resource-group myRG --name myFunctionApp --slot mySlot --query "[?name=='TEST_SETTING']"

    Result: Still shows {"name": "TEST_SETTING", "slotSetting": true, "value": "initial-value"} (unchanged)

  6. Try to update using JSON file:

    echo '{"TEST_SETTING": "updated-via-json"}' > test.json
    az functionapp config appsettings set --resource-group myRG --name myFunctionApp --slot mySlot --slot-settings @test.json
  7. Verify again - value remains unchanged

Additional Context

Click to expand Additional Context

Working Workarounds

  • Using --settings updates the value but incorrectly treats it as a regular setting instead of a slot setting
  • Inline parameter works for creating NEW slot settings, just not for updating existing ones

Core Issue Summary

The main problem is that --slot-settings parameter:

  • Works for creating new slot settings
  • Fails to update existing slot settings (regardless of input format)
  • Works when using --settings parameter (but incorrectly marks them as regular settings)

Impact

This bug prevents users from:

  • Automating deployment pipelines that need to update slot settings
  • Using configuration files to manage slot settings in CI/CD scenarios
  • Properly managing slot-specific configurations in multi-environment setups

My Local Investigation and Fixes

Click to expand My Local Investigation Results

I performed a local investigation of this issue and implemented fixes that resolve the problem in my environment. Here's what I discovered:

File Investigated

src/azure-cli/azure/cli/command_modules/appservice/custom.py

Root Cause Analysis

Through my investigation, I found the issue had two main components:

  1. JSON Processing: When using object format JSON {"KEY": "VALUE"}, the original code was putting values in the wrong variable (dest instead of result), so values were never applied.

  2. Timing: Even when values were processed correctly, the slot configuration was updated after the application settings, so Azure didn't know the settings should be slot-specific when the values were applied.

My Local Fix 1: JSON Object Format Support

What I Found (lines ~546-556):

                if isinstance(temp, list):  # Handle array format
                    for t in temp:
                        if 'slotSetting' in t.keys():
                            slot_result[t['name']] = t['slotSetting']
                        elif setting_type == "SlotSettings":
                            slot_result[t['name']] = True
                        result[t['name']] = t['value']
                else:
                    # PROBLEM: Object format always went to 'dest', not handling SlotSettings properly
                    dest.update(temp)

My Local Fix:

                if isinstance(temp, list):  # Handle array format
                    for t in temp:
                        if 'slotSetting' in t.keys():
                            slot_result[t['name']] = t['slotSetting']
                        elif setting_type == "SlotSettings":
                            slot_result[t['name']] = True
                        result[t['name']] = t['value']
                else:
                    # Handle JSON objects - when using --slot-settings with object format,
                    # treat all keys as slot settings
                    if setting_type == "SlotSettings":
                        # For slot settings, we need to add values to result (for app settings)
                        # AND mark them as slot settings in slot_result
                        result.update(temp)  # Add actual values to result
                        for key in temp.keys():
                            slot_result[key] = True  # Mark as slot setting
                    else:
                        dest.update(temp)  # Regular settings go to dest (which is result)

My Local Fix 2: Operation Reordering

Original Code Flow (lines ~600-620):

    for setting_name, value in result.items():
        app_settings.properties[setting_name] = value
    client = web_client_factory(cmd.cli_ctx)

    # TODO: Centauri currently return wrong payload for update appsettings, remove this once backend has the fix.
    if is_centauri_functionapp(cmd, resource_group_name, name):
        update_application_settings_polling(cmd, resource_group_name, name, app_settings, slot, client)
        result = _generic_site_operation(cmd.cli_ctx, resource_group_name, name, 'list_application_settings', slot)
    else:
        result = _generic_settings_operation(cmd.cli_ctx, resource_group_name, name,
                                             'update_application_settings',
                                             app_settings, slot, client)

    # PROBLEM: slot_result was processed AFTER application settings
    app_settings_slot_cfg_names = []
    if slot_result:
        slot_cfg_names = client.web_apps.list_slot_configuration_names(resource_group_name, name)
        # ... rest of slot configuration code

My Local Modification:

    for setting_name, value in result.items():
        app_settings.properties[setting_name] = value
    client = web_client_factory(cmd.cli_ctx)

    # Process slot configurations BEFORE updating application settings
    # This ensures that slot settings are properly configured before the values are applied
    app_settings_slot_cfg_names = []
    if slot_result:
        slot_cfg_names = client.web_apps.list_slot_configuration_names(resource_group_name, name)
        slot_cfg_names.app_setting_names = slot_cfg_names.app_setting_names or []
        # Slot settings logic to add a new setting(s) or remove an existing setting(s)
        for slot_setting_name, value in slot_result.items():
            if value and slot_setting_name not in slot_cfg_names.app_setting_names:
                slot_cfg_names.app_setting_names.append(slot_setting_name)
            elif not value and slot_setting_name in slot_cfg_names.app_setting_names:
                slot_cfg_names.app_setting_names.remove(slot_setting_name)
        app_settings_slot_cfg_names = slot_cfg_names.app_setting_names
        client.web_apps.update_slot_configuration_names(resource_group_name, name, slot_cfg_names)

    # TODO: Centauri currently return wrong payload for update appsettings, remove this once backend has the fix.
    if is_centauri_functionapp(cmd, resource_group_name, name):
        update_application_settings_polling(cmd, resource_group_name, name, app_settings, slot, client)
        result = _generic_site_operation(cmd.cli_ctx, resource_group_name, name, 'list_application_settings', slot)
    else:
        result = _generic_settings_operation(cmd.cli_ctx, resource_group_name, name,
                                             'update_application_settings',
                                             app_settings, slot, client)

Results of My Local Testing

With both fixes implemented locally, all scenarios now work correctly:

  • Inline Format: --slot-settings "KEY=value"
  • JSON Array Format: --slot-settings @array.json
  • JSON Object Format: --slot-settings @object.json
  • Updating Existing Settings: Values are correctly updated and slotSetting: true is maintained

Summary of My Fixes

  1. JSON Object Format Support: Added logic to handle JSON objects when setting_type == "SlotSettings" - values go to result AND keys are marked as slot settings in slot_result
  2. Operation Reordering: Moved slot configuration processing to BEFORE app settings update

I discovered that both fixes were necessary - the JSON fix ensures values are properly assigned, and the timing fix ensures Azure knows they're slot settings before applying the values.

Conclusion

I hope this documentation of my local investigation and the changes I implemented will help the Azure CLI team understand and resolve this issue in the official codebase. The fixes I've tested locally address both the JSON parsing problem and the operation timing issue, and all test scenarios now work correctly in my environment.

If you need any additional information about my investigation or would like me to test any specific scenarios, please let me know.

Labels

  • bug
  • App Service
  • Function App
  • slot-settings

Priority

Medium - This affects automation scenarios and deployment pipelines, but workarounds exist.

Metadata

Metadata

Labels

Auto-AssignAuto assign by botFunctionsaz functionappService AttentionThis issue is responsible by Azure service team.bugThis issue requires a change to an existing behavior in the product in order to be resolved.customer-reportedIssues that are reported by GitHub users external to the Azure organization.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions