evijit HF Staff Claude Opus 4.7 (1M context) commited on
Commit
93c113e
·
1 Parent(s): 6cfbb83

view-data: also wrap VARCHAR[] and TIMESTAMP columns; add app/error.tsx boundary

Browse files

The CAST-to-VARCHAR patch wasn't enough — `[view-data] readRows
failed` still surfaced in the deploy logs with the new SQL. The
remaining unwrapped columns in eval_results_view.r.* are two
VARCHAR[] (evaluator_relationships, reporting_orgs) and four
TIMESTAMP columns (snapshot_id, evaluation_timestamp,
benchmark_updated, retrieved_timestamp). Wrap the lists with
to_json+CAST and the timestamps with a plain CAST to VARCHAR so
nothing the binding might choke on slips through r.*.

Also adds app/error.tsx so a transient backend error renders a
friendly retry card instead of Next.js's bare "Application error: a
client-side exception has occurred" overlay — useful during cold
parquet warm-up if any request still fails before the cache is
hydrated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Files changed (2) hide show
  1. app/error.tsx +100 -0
  2. lib/view-data.ts +7 -1
app/error.tsx ADDED
@@ -0,0 +1,100 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use client"
2
+
3
+ import { useEffect } from "react"
4
+
5
+ /**
6
+ * Top-level error boundary for every route under app/. Next.js renders
7
+ * this when a server component throws or a client render exception
8
+ * escapes the closest boundary. Replaces the bare default
9
+ * "Application error: a client-side exception has occurred" overlay
10
+ * with a recoverable affordance so a transient backend hiccup (cold
11
+ * parquet cache, slow first query) doesn't strand the reader on an
12
+ * unfriendly screen.
13
+ */
14
+ export default function RouteError({
15
+ error,
16
+ reset,
17
+ }: {
18
+ error: Error & { digest?: string }
19
+ reset: () => void
20
+ }) {
21
+ useEffect(() => {
22
+ if (typeof window !== "undefined" && "console" in window) {
23
+ console.error("[route-error]", error)
24
+ }
25
+ }, [error])
26
+
27
+ return (
28
+ <div
29
+ style={{
30
+ minHeight: "60vh",
31
+ display: "flex",
32
+ alignItems: "center",
33
+ justifyContent: "center",
34
+ padding: "24px",
35
+ }}
36
+ >
37
+ <div
38
+ style={{
39
+ maxWidth: 460,
40
+ width: "100%",
41
+ padding: "28px 28px 24px",
42
+ border: "1px solid var(--border-soft)",
43
+ background: "var(--bg)",
44
+ }}
45
+ >
46
+ <div
47
+ className="font-mono uppercase"
48
+ style={{
49
+ fontSize: 10,
50
+ letterSpacing: "0.18em",
51
+ color: "var(--fg-subtle)",
52
+ marginBottom: 14,
53
+ }}
54
+ >
55
+ Something went wrong
56
+ </div>
57
+ <p
58
+ style={{
59
+ margin: 0,
60
+ color: "var(--fg)",
61
+ fontSize: 15,
62
+ lineHeight: 1.55,
63
+ }}
64
+ >
65
+ We couldn't load this view. The data backend may still be
66
+ warming up — most cold-start hiccups clear within a few
67
+ seconds.
68
+ </p>
69
+ <div
70
+ style={{
71
+ display: "flex",
72
+ gap: 10,
73
+ marginTop: 20,
74
+ flexWrap: "wrap",
75
+ }}
76
+ >
77
+ <button type="button" className="btn-ec" onClick={() => reset()}>
78
+ Try again
79
+ </button>
80
+ <a href="/" className="btn-ec outline">
81
+ Back to home
82
+ </a>
83
+ </div>
84
+ {error.digest && (
85
+ <div
86
+ className="font-mono"
87
+ style={{
88
+ marginTop: 18,
89
+ fontSize: 10,
90
+ color: "var(--fg-subtle)",
91
+ wordBreak: "break-all",
92
+ }}
93
+ >
94
+ ref: {error.digest}
95
+ </div>
96
+ )}
97
+ </div>
98
+ </div>
99
+ )
100
+ }
lib/view-data.ts CHANGED
@@ -102,7 +102,13 @@ const CELL_JOIN_COLUMNS = `
102
  CAST(to_json(r.eval_library) AS VARCHAR) AS eval_library,
103
  CAST(to_json(r.aggregate_components) AS VARCHAR) AS aggregate_components,
104
  CAST(to_json(r.evalcards_annotations) AS VARCHAR) AS evalcards_annotations,
105
- CAST(to_json(r.scores_by_organization) AS VARCHAR) AS scores_by_organization
 
 
 
 
 
 
106
  ),
107
  e.evaluation_name AS eval_evaluation_name,
108
  e.canonical_display_name AS eval_canonical_display_name,
 
102
  CAST(to_json(r.eval_library) AS VARCHAR) AS eval_library,
103
  CAST(to_json(r.aggregate_components) AS VARCHAR) AS aggregate_components,
104
  CAST(to_json(r.evalcards_annotations) AS VARCHAR) AS evalcards_annotations,
105
+ CAST(to_json(r.scores_by_organization) AS VARCHAR) AS scores_by_organization,
106
+ CAST(to_json(r.evaluator_relationships) AS VARCHAR) AS evaluator_relationships,
107
+ CAST(to_json(r.reporting_orgs) AS VARCHAR) AS reporting_orgs,
108
+ CAST(r.snapshot_id AS VARCHAR) AS snapshot_id,
109
+ CAST(r.evaluation_timestamp AS VARCHAR) AS evaluation_timestamp,
110
+ CAST(r.benchmark_updated AS VARCHAR) AS benchmark_updated,
111
+ CAST(r.retrieved_timestamp AS VARCHAR) AS retrieved_timestamp
112
  ),
113
  e.evaluation_name AS eval_evaluation_name,
114
  e.canonical_display_name AS eval_canonical_display_name,