pinpoint-apm/pinpoint · warning
TRANSACTION_LIST.LINKED_TRANSACTION_NOT_FOUND
Error message
TRANSACTION_LIST.LINKED_TRANSACTION_NOT_FOUND
What it means
A toast warning shown when the OTEL trace-to-Pinpoint transaction link button cannot resolve the linked transaction. The code fetches the trace's span metadata rows; if no row has an applicationName or serviceType, it cannot build the transaction search URL, so it warns instead of navigating.
Solutions
- Verify the trace metadata API returns rows with applicationName and serviceType populated for the given traceId/spanId
- Check that the OTEL collector/pinpoint is mapping service.name and service.type resource attributes correctly
- Retry the link after the trace is fully processed (data may still be ingesting)
- Fall back to searching the transaction manually from the transaction list
Example fix
// before
const preferred = rows.find((row) => String(row.spanId) === spanId) || rows[0];
if (!preferred?.applicationName || !preferred?.serviceType) {
toast.warn(t('TRANSACTION_LIST.LINKED_TRANSACTION_NOT_FOUND'));
return;
}
// after
const preferred = rows.find((row) => String(row.spanId) === spanId) || rows[0];
if (!preferred?.applicationName || !preferred?.serviceType) {
toast.warn(t('TRANSACTION_LIST.LINKED_TRANSACTION_NOT_FOUND'));
// optionally: fall back to first row that HAS application info
const anyValid = rows.find((r) => r.applicationName && r.serviceType);
if (!anyValid) return;
preferred = anyValid;
} Defensive patterns
Strategy: fallback
Validate before calling
const rows = data?.metadata ?? []; const preferred = rows.find((r) => String(r.spanId) === spanId) || rows[0]; const linkable = !!preferred?.applicationName && !!preferred?.serviceType;
Type guard
const isLinkableRow = (row?: { applicationName?: string; serviceType?: string }): row is { applicationName: string; serviceType: string } =>
typeof row?.applicationName === 'string' && row.applicationName.length > 0 &&
typeof row?.serviceType === 'string' && row.serviceType.length > 0; Prevention
- Guard with optional chaining before reading preferred.collectorAcceptTime and other fields
- Ensure OTEL exporters set service.name/service.type resource attributes
- Handle empty trace metadata responses explicitly in the UI
- Test link buttons against traces with missing or partial spans
When it happens
Trigger: Clicking the OTEL link button on a transaction whose trace metadata is empty, or whose resolved preferred row (span matching the link's spanId, else the first row) lacks applicationName or serviceType.
Common situations: OTLP traces ingested without application/service attributes; the linked spanId points to a sub-span whose row is missing; stale link to a trace that no longer has metadata rows; partially ingested trace data.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- An error occurred while fetching the data.
- Out of date range.
- Request failed with status
- Resource attribute `service.name` is required to save OTLP…
AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07).
Data as JSON: /api/errors/bf831dff1cebf16e.
Report an issue: GitHub.
Appendix: source
Thrown at web-frontend/src/main/v3/packages/ui/src/components/Transaction/call-tree/callTreeTableColumns.tsx:780
// 않고, 열린 화면이 전역 선택값으로 조회한다(`resolveRequestService`).
const { serviceName } = useTransactionSearchParameters();
const handleClick = async (e: React.MouseEvent) => {
e.stopPropagation();
// fetch errors already surface via the global query error toast
const data = await queryClient
.fetchQuery(getTransactionTraceMetadataQueryOptions(traceId))
.catch(() => null);
if (data === null) {
return;
}
const rows = data?.metadata ?? [];
// A trace may contain multiple spans (multi-application); prefer the span the
// link points to, falling back to the first row (e.g. link target is a sub-span).
const preferred = rows.find((row) => String(row.spanId) === spanId) || rows[0];
if (!preferred?.applicationName || !preferred?.serviceType) {
toast.warn(t('TRANSACTION_LIST.LINKED_TRANSACTION_NOT_FOUND'));
return;
}
const baseTime = preferred.collectorAcceptTime;
const from = formatInTimeZone(baseTime - 150000, timezone, SEARCH_PARAMETER_DATE_FORMAT);
const to = formatInTimeZone(baseTime + 150000, timezone, SEARCH_PARAMETER_DATE_FORMAT);
const path = getTransactionListPath(
{ applicationName: preferred.applicationName, serviceType: preferred.serviceType },
undefined,
serviceName,
);
const url = `${BASE_PATH}${path}?${convertParamsToQueryString({
from,
to,
traceInfo: traceId,
transactionInfo: JSON.stringify({
agentId: preferred.agentId,
spanId: preferred.spanId,View on GitHub (pinned to 744c3d3075)