Skip to content

Fix UnboundLocalError in aws configure set for nested values - #10555

Open
Adityaj0 wants to merge 1 commit into
aws:v2from
Adityaj0:fix/configure-set-nested-unbound-local
Open

Fix UnboundLocalError in aws configure set for nested values#10555
Adityaj0 wants to merge 1 commit into
aws:v2from
Adityaj0:fix/configure-set-nested-unbound-local

Conversation

@Adityaj0

Copy link
Copy Markdown

Issue

Fixes #10554

Description of changes

aws configure set <section>.<key>.<subkey> <value> crashes with an internal UnboundLocalError and exit code 255 when the nested parent key is not immediately followed by another indented option line:

$ AWS_CONFIG_FILE=./config aws configure set default.s3.max_concurrent_requests 20

aws: [ERROR]: cannot access local variable 'current_indent' where it is not associated with a value

In ConfigFileWriter._update_subattributes, current_indent is only assigned inside the if match is not None: branch, and i is only assigned if the for loop body runs. Both are read unconditionally afterwards:

if (
    starting_indent == current_indent      # unbound if no line matched yet
    or self.SECTION_REGEX.search(line) is not None
):
    ...
else:
    if starting_indent != current_indent:  # unbound if the range was empty
        self._insert_new_values(i, contents, values, '    ')

Comments and blank lines do not match OPTION_REGEX, so if one of those directly follows the parent key, current_indent is never bound. If the parent key is the last line in the file, range() is empty and both current_indent and i are unbound when the else: clause runs.

Three valid config layouts trigger it — all three parse correctly via botocore.configloader.raw_config_parse:

[default]        [default]        [default]
s3 =             s3 =             s3 =
# comment
                                  (blank line)

The fix seeds both names before the loop:

current_indent = None
i = index - 1

This is behaviour-preserving for every input that previously worked. current_indent is read only at those two comparison sites, and None never compares equal to starting_indent — which is exactly the "this line does not end the nested block" outcome that a stale-but-different indent already produced for comments appearing later within a block. In the else: clause the comparison was already unconditionally true whenever it was reached, since an equal indent would have broken out of the loop. Seeding i with the nested key's own line makes the values get appended directly after it when nothing follows.

Resulting output for the three cases above:

[default]                                  [default]
s3 =                                       s3 =
# comment                                      signature_version = newval
    signature_version = newval

[default]
s3 =

    signature_version = newval

Testing

Three regression tests added to tests/unit/customizations/configure/test_writer.py, one per layout. Each fails with UnboundLocalError on v2 and passes with the fix.

  • tests/unit/customizations/configure/ and tests/functional/configure/: 313 passed
  • tests/unit/customizations/: no new failures (the single failure, test_emr_utils.py::TestEMRutils::test_which_with_existing_command, reproduces identically on unmodified v2 in this environment and is unrelated)
  • Verified end to end that aws configure set default.s3.max_concurrent_requests 20 now exits 0, and that aws configure get default.s3.max_concurrent_requests reads the value back.

Both touched files already fail ruff format --check/ruff check on unmodified v2, so I deliberately left the surrounding formatting alone rather than growing the diff; the added lines introduce no new findings.

`ConfigFileWriter._update_subattributes` only assigns `current_indent`
inside the `if match is not None:` branch but reads it unconditionally,
and reads `i` in the loop's `else:` clause. Both are unbound when the
line after the nested key does not parse as an option, or when the
loop body never runs at all.

This made `aws configure set <section>.<key>.<subkey> <value>` abort
with `UnboundLocalError` and exit 255, leaving the config untouched, for
three valid config layouts: the nested key followed by a comment, by a
blank line, or being the last line of the file.

Seed both names before the loop. `None` never compares equal to
`starting_indent`, preserving the existing behaviour that a non-option
line does not terminate the nested block, and seeding `i` with the
nested key's own line appends the values directly after it when nothing
follows.

Fixes aws#10554

Co-Authored-By: Claude Opus 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