Skip to content

aws configure set s3.* can raise UnboundLocalError when updating nested config blocks #10348

@fallintoplace

Description

@fallintoplace

Describe the bug

aws configure set s3.signature_version s3v4 can crash when the target config already has a nested s3 = block and the next line is not another option line.

I reproduced this with all of the following existing config shapes:

  • an empty nested block
  • a comment immediately after s3 =
  • an immediate next section header after s3 =

The crash comes from ConfigFileWriter._update_subattributes() reading current_indent even when OPTION_REGEX did not match the current line.

Regression Issue

This does not look like a recent regression. git blame shows _update_subattributes() was introduced with this behavior in 9c2fd8098a.

Expected Behavior

Updating a nested config value should append or update the nested key without crashing.

For example, starting from:

[default]
s3 =
# comment
    addressing_style = path

setting s3.signature_version should produce:

[default]
s3 =
# comment
    addressing_style = path
    signature_version = s3v4

Current Behavior

An uncaught traceback is raised:

Traceback (most recent call last):
  File "/Users/hoangvu/Code/OSS/aws-cli/awscli/customizations/configure/writer.py", line 115, in update_config
    self._update_section_contents(contents, section_name, new_values)
  File "/Users/hoangvu/Code/OSS/aws-cli/awscli/customizations/configure/writer.py", line 203, in _update_section_contents
    j = self._update_subattributes(
  File "/Users/hoangvu/Code/OSS/aws-cli/awscli/customizations/configure/writer.py", line 231, in _update_subattributes
    if starting_indent == current_indent or \
                          ^^^^^^^^^^^^^^
UnboundLocalError: cannot access local variable 'current_indent' where it is not associated with a value

Reproduction Steps

Minimal reproducer:

from awscli.customizations.configure.writer import ConfigFileWriter
import os
import tempfile

fd, path = tempfile.mkstemp()
os.close(fd)

with open(path, "w") as f:
    f.write("[default]\ns3 =\n# comment\n    addressing_style = path\n")

ConfigFileWriter().update_config(
    {"__section__": "default", "s3": {"signature_version": "s3v4"}},
    path,
)

This also reproduces with:

[default]
s3 =

and:

[default]
s3 =
[profile other]
region = us-east-1

Possible Solution

Handle non-option lines before comparing indentation, or initialize current_indent safely.

For example, _update_subattributes() could skip lines where OPTION_REGEX does not match, while still treating a new section header as the boundary for inserting new nested values.

It would also be helpful to add regression tests in tests/unit/customizations/configure/test_writer.py for:

  • empty nested blocks
  • comments after s3 =
  • section headers immediately after s3 =

Additional Information/Context

I reproduced this against the current develop checkout:

  • aws-cli/1.45.14
  • develop @ b698a6a77
  • macOS 26.5 arm64
  • Python 3.13.2

The user-facing path appears to be aws configure set s3.signature_version ..., but the minimal reproducer above avoids unrelated environment/setup dependencies.

CLI version used

aws-cli/1.45.14

Environment details (OS name and version, etc.)

macOS 26.5 arm64, Python 3.13.2

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions