Skip to content

verify export: long tokens can be wrapped with a literal newline, causing valid tokens to fail decoding #121

Description

@madebygps

Problem

Related to #120: a learner's completion token was rejected by learntocloud.guide with "Invalid token format. Could not decode the token." even though the token itself was valid once whitespace was stripped.

Root cause

export_certificate() in verify/src/verify/commands.py prints the ~328-char base64 token with:

console.print(token)

Rich's Console.print() measures the actual terminal width and, for output that exceeds it, inserts a literal newline character to wrap the line (this is real line-wrapping done by Rich, not just visual/soft terminal wrapping). I confirmed this locally: printing a 328-char string through a rich.console.Console at width 254 produces two lines joined by an actual \n in the captured output.

This means:

  • Narrow terminals (~80–254 cols, common in default SSH sessions, some SSH clients, smaller windows) will wrap the token and embed a real newline in it.
  • Wide terminals (IDE integrated terminals, maximized windows, tmux with many columns) usually don't hit this, which is likely why it's not more widely reported.

The README's own troubleshooting steps (save to ~/token.txt, view in nano) preserve this embedded newline rather than fixing it, since it's a real character in the file, not a rendering artifact.

Suggested fix

Print the token without Rich's line-wrapping, e.g.:

console.print(token, soft_wrap=True)

or bypass Rich entirely for this one line (print(token)), so the token is always emitted as a single line regardless of terminal width.

Reproduction

from rich.console import Console

token = "A" * 328
console = Console(width=80, record=True, force_terminal=False)
console.print(token)
out = console.export_text()
print(out.count("\n"))  # >1, confirms embedded literal newlines

Related

  • Token not being accepted after lab completion #120 (original report)
  • Companion defense-in-depth fix landed on the app side in learn-to-cloud-app (strips embedded whitespace before decoding), but the wrapping itself should still be fixed at the source here.

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions