aws history show/list: UnboundLocalError instead of clear error when pager fails to start

Abierto Apto para principiantes
#10,581 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 2 días

@Adityaj0 ya está trabajando en esto.

Desde el 18/8/2026.

  • #10582 de @Adityaj0 — abierto

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
68/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
aws, python
Área
cli

Línea de trabajo

Comienza en awscli/utils.py, en OutputStreamFactory.get_pager_stream, y luego lee tests/unit/test_utils.py::TestOutputStreamFactory y su prueba existente de error del pager. Ejecuta las pruebas específicas y confirma que un fallo al iniciar un pager informa del error original en lugar de UnboundLocalError, mientras el caso de broken pipe sigue cubierto.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

needs-triage

Describe the bug

OutputStreamFactory.get_pager_stream (awscli/utils.py) is used by aws history show / aws history list to pipe output through a pager when running in a TTY. The try/except OSError/finally structure is meant to gracefully ignore OSErrors (e.g. broken pipe when the pager is closed abruptly):

@contextlib.contextmanager
def get_pager_stream(self, preferred_pager=None):
    popen_kwargs = self._get_process_pager_kwargs(preferred_pager)
    try:
        process = self._popen(**popen_kwargs)
        yield process.stdin
    except OSError:
        # Ignore IOError since this can commonly be raised when a pager
        # is closed abruptly and causes a broken pipe.
        pass
    finally:
        process.communicate()

The try block covers both process creation (self._popen(...)) and process usage (yield process.stdin). If self._popen(...) itself raises OSError — which happens whenever the configured pager binary doesn't exist (FileNotFoundError is an OSError subclass), e.g. AWS_PAGER/PAGER is misconfigured, or a minimal system has no less installed — then process is never assigned. The except OSError: pass swallows that exception, but the finally: process.communicate() then references the undefined local variable process, raising an unrelated UnboundLocalError instead of a clear error about the pager.

Repro

from awscli.utils import OutputStreamFactory

def bad_popen(*args, **kwargs):
    raise OSError('no such file or directory: nonexistentpager')

factory = OutputStreamFactory(bad_popen)
with factory.get_pager_stream('nonexistentpager'):
    pass

Output:

Traceback (most recent call last):
  ...
  File "awscli/utils.py", line 253, in get_pager_stream
    process.communicate()
UnboundLocalError: cannot access local variable 'process' where it is not associated with a value

Real-world trigger

Any user of aws history show/aws history list running in a TTY with AWS_PAGER/PAGER set to a nonexistent or misspelled command gets this confusing UnboundLocalError traceback instead of a clear "pager not found" style error.

Suggested fix

Only wrap the yield (process usage) in the try/except that's meant to swallow broken-pipe errors; let a failure to start the process propagate normally:

process = self._popen(**popen_kwargs)
try:
    yield process.stdin
except OSError:
    pass
finally:
    process.communicate()

I have a PR ready with this fix plus a regression test in tests/unit/test_utils.py::TestOutputStreamFactory that reproduces the UnboundLocalError against the current code and passes with the fix.

Environment

  • aws-cli develop branch (current)
  • Confirmed no existing test in tests/unit/test_utils.py::TestOutputStreamFactory exercises self._popen(...) itself raising OSError (existing test_can_silence_io_error_from_pager only covers process.stdin access raising after Popen succeeds).
Lenguaje dominante
Python
Estrellas
17.4k
Forks
4.8k
Merge medio
4 d 3 h
PR fusionados (30 d)
64

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de aws/aws-cli

Todos los issues de aws/aws-cli

Issues similares

Más issues de Python

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.