TRON transaction expiration is an inclusion deadline in raw_data.expiration, expressed as Unix milliseconds. It is different from the transaction’s creation timestamp, its block time and an OUT_OF_TIME execution result. A historical deadline passing does not undo a transaction that was already included.
This TRON transaction expiration audit helps you interpret an expiry warning before deciding what evidence is still missing. We compare three real time fields, provide a tested local converter and show how to write a diagnostic note. The method does not sign, rebroadcast, extend or replace any transaction.
Checked October 28, 2026 by the independent Tronscan News editorial team. AI assisted drafting and original diagrams. We checked the primary sources, compared one retrieved Mainnet body with a solidified-state receipt response, and ran thirteen synthetic local fixtures. We did not test a failed broadcast, a replacement payment or exchange credit. Editorial and correction policies are available through About & Standards.

Table of Contents
1. Separate the three TRON transaction expiration clocks
The official transaction protocol guide distinguishes raw_data.timestamp from raw_data.expiration. The creation field is a construction-time hint; expiration controls inclusion eligibility. The containing block supplies the on-chain time.
| Field | Role in this audit | Do not substitute |
|---|---|---|
raw_data.timestamp |
Recorded creation time in the transaction body | The exact time a block included it |
raw_data.expiration |
The transaction’s inclusion deadline | An automatic reversal or refund time |
blockTimeStamp in transaction info |
Reported timestamp of the containing block | Your device’s current time |
Node-built transactions normally derive a default deadline from the chain head, rather than simply adding a minute to raw_data.timestamp. Defaults and construction overrides are not a reason to replace the actual field. In particular, do not assume expiration minus timestamp must equal exactly 60,000 milliseconds.
Write the field name next to every time you copy. A screenshot containing three unlabeled clock values leaves the most important question unanswered: which clock does each value describe? Our TRON transaction expiration worksheet keeps the original integer and a labelled UTC display together so another reader can check the conversion.
This audit is narrower than a general error-code tutorial. For the broader distinction between validation and execution outcomes, use our TRON transaction error guide. An expiry label should not become an instruction to buy more resources without checking the actual source and stage.
2. Reproduce the TRON transaction expiration observation
We reused a transaction body retrieved during a separate read-only field check on October 28. It came from the first transaction in one returned current Mainnet block, not a random or representative sample. The complete transaction ID is c9b38bc4f2cdce616d2b23e8d45e118438128fbc592d33e1c4f5a7f28cf931f2.
At 04:59:14 UTC we queried https://api.trongrid.io/walletsolidity/gettransactioninfobyid with that ID. The response was HTTP 200, matched the body’s ID and reported block number 87,496,515. This was a hosted provider’s solidified-state endpoint response; we did not independently audit the provider’s node synchronization.
| Observed source field | Original integer, milliseconds | UTC display on October 28, 2026 |
|---|---|---|
| raw_data.timestamp | 1793162819934 | 04:46:59.934 UTC |
| blockTimeStamp | 1793162823000 | 04:47:03.000 UTC |
| raw_data.expiration | 1793162877000 | 04:47:57.000 UTC |
The integer subtraction gives 1793162877000 - 1793162819934 = 57066 milliseconds between the recorded creation and expiration. It gives 1793162877000 - 1793162823000 = 54000 milliseconds between the reported block time and expiration.
These are observations from one record. They do not establish a standard lifetime, average confirmation speed or typical delay. We did not observe when a sender pressed a button or when a node first received the payload. The recorded creation-to-block difference is therefore not a measured end-to-end payment latency.
The body returned contractRet SUCCESS. The selected receipt response did not include a receipt.result member; we did not invent one to complete the table. The audit uses the matched ID and reported block fields for the time comparison. It is not an exchange-credit confirmation or a full validation of every execution field.
Notice that the read-only receipt query happened after the displayed deadline. The response still reported the historical containing block. TRON transaction expiration is not a timer that erases that record after inclusion. This example is useful precisely because it separates a past deadline from the question of whether an original transaction was ever included.
3. Collect evidence for a TRON transaction expiration warning
- Retain the original network, complete transaction ID and exact warning text. Record whether it came from a wallet screen, a submission response or an execution receipt.
- Retrieve the transaction body on the intended network. Save the complete response, not only a converted time.
- Locate raw_data.expiration and, when present, raw_data.timestamp. Keep the original millisecond integers.
- If transaction info is available, match its ID to the body before comparing blockTimeStamp. Do not combine fields from two different transactions.
- Convert all selected times with an explicit timezone and preserve unknown fields as unknown.
- Classify what remains unresolved. A local clock passing the deadline or one empty response does not by itself settle an earlier submission’s outcome.
The transaction-body API reference explains that the body and execution receipt are different responses. Check the returned content as well as its HTTP status. An error body is not a valid transaction with missing times.
A body lookup and a receipt lookup can become available at different stages. This workflow does not turn a single missing response into proof of absence. Record the endpoint and retrieval time so a later check can be compared with the same scope.

4. Test the TRON transaction expiration timestamp conversion
Save the following example as inspect_times.py. Put your saved body in transaction-body.json and its matching receipt response in solidified-receipt.json, then run python inspect_times.py. The program reads those local files only. It does not request, construct, sign or broadcast a transaction.
import json
from datetime import datetime, timezone
from pathlib import Path
def milliseconds(value):
if isinstance(value, str) and value.isascii() and value.isdecimal():
value = int(value)
if type(value) is not int or not 0 <= value < 2**63:
raise ValueError("Expected non-negative Unix milliseconds")
return value
def utc_time(value):
seconds, remainder = divmod(milliseconds(value), 1000)
try:
instant = datetime.fromtimestamp(seconds, timezone.utc)
return instant.replace(microsecond=remainder * 1000).isoformat(timespec="milliseconds")
except (OverflowError, OSError, ValueError):
raise ValueError("Timestamp outside local datetime range")
def inspect_times(body, receipt=None):
if not isinstance(body, dict) or "Error" in body:
raise ValueError("Expected a transaction body")
raw = body.get("raw_data")
if not isinstance(raw, dict) or "expiration" not in raw:
raise ValueError("Missing raw_data.expiration")
deadline = milliseconds(raw["expiration"])
result = {"expiration_ms": deadline, "expiration_utc": utc_time(deadline)}
if "timestamp" in raw:
created = milliseconds(raw["timestamp"])
result.update(creation_ms=created, creation_utc=utc_time(created),
expiration_minus_creation_ms=deadline-created)
if receipt is not None:
if not isinstance(receipt, dict) or "Error" in receipt:
raise ValueError("Expected a receipt object")
if body.get("txID") != receipt.get("id") or not body.get("txID"):
raise ValueError("Body and receipt IDs must match")
if "blockTimeStamp" in receipt:
included = milliseconds(receipt["blockTimeStamp"])
result.update(block_ms=included, block_utc=utc_time(included),
expiration_minus_block_ms=deadline-included)
return result
if __name__ == "__main__":
body = json.loads(Path("transaction-body.json").read_text(encoding="utf-8"))
receipt = json.loads(Path("solidified-receipt.json").read_text(encoding="utf-8"))
print(json.dumps(inspect_times(body, receipt), indent=2))
Python’s datetime documentation distinguishes timezone-aware conversions from ambiguous local displays. The example explicitly chooses UTC. Integer division separates whole seconds and remaining milliseconds, avoiding a floating-point intermediate for the displayed fractional second.
The result for our saved observation includes the three UTC times above, expiration_minus_creation_ms of 57066 and expiration_minus_block_ms of 54000. The TRON transaction expiration converter intentionally does not print a verdict such as safe to replace, expired on every node or never included. It is a field extractor and converter, not a protocol-validity or payment-safety engine.
A missing creation timestamp remains absent from the output. The program does not insert a default creation time just to obtain a duration. Similarly, without a receipt argument, the function can convert the body’s deadline but cannot invent a block time. Keep the unresolved field visible in your note.
The input policy accepts non-negative integer milliseconds and decimal integer strings. It rejects booleans, fractional values, negative values, non-decimal strings and integers outside the signed 64-bit range. A timestamp that cannot be displayed by the local datetime implementation also produces an explicit error.
5. Check the local fixtures and their limits
We ran thirteen synthetic local fixtures in addition to the real body/receipt comparison. All behaved as intended. These tests check extraction and UTC conversion. They do not submit an expired payload to a node, measure a pending pool or test a payment replacement.
| Synthetic fixture | Observed local behavior | Boundary tested |
|---|---|---|
| 0 milliseconds | 1970-01-01T00:00:00.000+00:00 | Epoch conversion; not an execution status |
| 1 millisecond | 1970-01-01T00:00:00.001+00:00 | Exact millisecond remainder |
| Decimal string 1000 | 1970-01-01T00:00:01.000+00:00 | Explicit integer-string input |
| Boolean; float; negative; text with ms suffix | ValueError in each case | Four invalid input shapes stay invalid |
| Integer beyond int64; datetime display overflow | ValueError in each case | Two different range checks |
| Creation field removed | No invented creation field in output | Missing data remains unknown |
| Missing deadline; Error-only body; mismatched receipt ID | ValueError in each case | Three source-comparison failures stop the audit |
Passing a timestamp in seconds instead of milliseconds is a different problem from an invalid Python type. A value may be a perfectly valid integer and still use the wrong unit. The converter cannot infer your intended unit from context, so check the API field definition before using the result.
Synthetic unit exercise: divide one of our real millisecond integers by 1,000, discard the remainder, and then mistakenly feed that smaller integer into a millisecond converter. The displayed date will be near the Unix epoch rather than October 2026. That implausible display should prompt a unit check; it does not prove the transaction expired decades earlier.
Timezone errors can look less obvious because the date may still appear plausible. A display of 12:47:57 at UTC+08:00 and 04:47:57 UTC can identify the same instant. Compare timezone-aware times or the original integers rather than treating the eight-hour display difference as a different deadline.

6. Diagnose the stage before interpreting expired or OUT_OF_TIME
The official broadcast-error reference explains that TRANSACTION_EXPIRATION_ERROR concerns the node’s accepted deadline range. It can involve a deadline too early for inclusion or too far ahead of the chain head. A short wallet label alone does not identify which condition applied.
The same reference’s replacement procedure warns that a passed local clock, a timeout or one empty query does not establish that an earlier submission was absent from solidified history. Keep the original transaction ID and investigate that original record before considering a newly constructed payment. This article does not perform or certify that full history investigation.
The official error-category guide separates submission validation from on-chain execution. OUT_OF_TIME is an execution result that requires the exact associated message; it is not simply another spelling of an expired inclusion deadline. A specific protocol check can also trigger the result.
| What you actually have | Question to answer next | Unsupported shortcut to avoid |
|---|---|---|
| Wallet expiry notification | What underlying response and field caused it? | Assuming every node rejected every earlier submission |
| Submission response with an expiration error | What was the deadline relative to the node’s chain context? | Changing a field in an already signed payload without considering identity and authorization |
| Receipt with OUT_OF_TIME | What exact execution message and transaction record are reported? | Adding a minute to a deadline as though it repairs execution |
| Historical included record with a now-past deadline | What outcome and block does the record report? | Calling it reversed because the wall clock advanced |
| Unknown submission outcome and an empty lookup | Has the original ID been checked with adequate solidified-history coverage? | Authorizing a duplicate payment from a single absence |
Our example supplies a historical matched record, not a reproduction of an expiration error. Do not cite it as proof that a particular failed submission could have succeeded. The actual source of a warning still matters, and a provider’s unavailable history should remain a documented limitation.
For ordinary record discovery, return to our transaction lookup walkthrough. For retaining the responses used in an audit, use our read-only record preservation method. These tasks support the investigation without pretending to authorize a replacement transfer.
7. Write a TRON transaction expiration evidence note
Use this original worksheet to make the next handoff specific. It is an on-page template, not a downloadable receipt. An unresolved item should stay labelled unknown, even if that makes the note less tidy.
| Group | Record these fields | Reason |
|---|---|---|
| Identity | Network, complete original TxID, source of that ID | A second transaction cannot supply the first one’s outcome |
| Body | Retrieval UTC, endpoint, raw expiration and creation integers | Keeps source times separate from display formatting |
| Receipt | Endpoint scope, retrieval UTC, matched ID, block time and number when returned | Documents the available inclusion context |
| Warning | Exact code, exact message, stage and observation time | Prevents validation and execution from being merged |
| Limits | Missing responses, unverified synchronization, incomplete historical coverage | Shows what the clock comparison cannot settle |
Review a completed note in two passes: first check identity and units, then check the interpretation. In the first pass, compare the full IDs, original integers, endpoint scope and timezone labels. In the second, underline each conclusion and identify the specific source field that supports it. If a conclusion depends only on a local clock or an unavailable lookup, keep it unresolved rather than promoting it to a payment outcome.
This two-pass review makes TRON transaction expiration comparisons easier to reproduce. It also lets a later investigator add a newly available receipt without silently changing the earlier collection. Record the added source and time as new evidence, while preserving the original note’s limits.
Keep raw responses and derived UTC displays in separate files or clearly labelled sections. Do not replace an original integer with a human-readable date and discard the source. Someone checking the note should be able to reproduce both the unit conversion and the ID match.
When a support provider answers, attach its explanation to the original case rather than rewriting your earlier observation. A later endpoint result may add information, but it does not change what was available at the first retrieval time. This distinction matters when a wallet, node and explorer update at different moments.

A complete TRON transaction expiration note answers what time field was inspected, which record it belonged to and which question remains open. It does not need an invented success claim. The Tronscan News homepage provides the wider English guide collection for the next verified step.
Frequently asked questions
Does TRON transaction expiration reverse an included transfer?
No. It is an inclusion deadline, not a historical reversal timer. Inspect the matched transaction and receipt records for the reported outcome rather than interpreting a now-past deadline as a refund.
Must expiration minus creation equal exactly sixty seconds?
No. The fields have different construction roles and can vary. Our one observed record had a difference of 57,066 milliseconds. That observation is not a standard lifetime or a reason to overwrite another transaction’s actual fields.
Is OUT_OF_TIME the same as an expiration error?
No. OUT_OF_TIME is an execution result requiring its exact accompanying message. A submission expiration error concerns the deadline range checked by a node. Diagnose the stage before choosing a next action.
Can one empty query prove that an expired transaction was never included?
No. An empty result may reflect the endpoint or its available history. A passed local clock also does not settle an earlier submission’s outcome. Preserve the original ID and resolve the missing history before considering a replacement.
Does the local converter extend or validate a transaction?
No. It reads saved fields, converts their times and calculates differences. It does not inspect a live node’s acceptance window, sign changes, broadcast a payload or certify that another payment is safe.
Leave a Reply