larksuite/cli · error

trailing data after JSON value

Error message

trailing data after JSON value

What it means

decoderExpectEOF validates that a JSON payload (--sheets/--values) contains exactly one JSON value. After decoding the first value it tries another Decode; if that succeeds, trailing data existed after the value, so this plain error is thrown. It prevents payloads like `{...} garbage` from being silently truncated to the leading object.

Source

Thrown at shortcuts/sheets/lark_sheet_table_io.go:326

		return "float64"
	case "date":
		return "datetime64[ns]"
	case "bool":
		return "bool"
	default:
		return "object"
	}
}

// decoderExpectEOF ensures the decoder has nothing left to read after a
// successful Decode. json.Decoder accepts trailing non-whitespace after the
// first JSON value (unlike json.Unmarshal), so a payload like `{...} trailing`
// would silently be treated as the leading object only. Use this after the
// first Decode to surface the trailing data as a validation error.
func decoderExpectEOF(dec *json.Decoder) error {
	var trailing json.RawMessage
	if err := dec.Decode(&trailing); err == nil {
		return fmt.Errorf("trailing data after JSON value") //nolint:forbidigo // intermediate error; the caller wraps it into a typed --sheets/--values validation error
	} else if !errors.Is(err, io.EOF) {
		return fmt.Errorf("trailing data after JSON value: %w", err) //nolint:forbidigo // intermediate error; the caller wraps it into a typed --sheets/--values validation error
	}
	return nil
}

// tablePutSheetsSkeleton is the one-line --sheets shape inlined on a decode
// error, so the retry needs no --print-schema round trip. Field vocabulary
// mirrors tableSheetIn.
const tablePutSheetsSkeleton = `{"sheets":[{"name":"Sheet1","columns":["City","Revenue"],"dtypes":{"Revenue":"float64"},"data":[["SH",123.4],["BJ",56.7]],"start_cell":"A1"}]}`

// parseTablePutPayload reads --sheets (JSON, supports @file / stdin) into a
// validated payload. UseNumber keeps numeric cells as json.Number so large
// integers (order IDs, etc.) survive without precision loss or scientific
// notation. The wire shape (tableSheetIn: string columns + dtypes/formats maps
// + `data`) is normalized into the internal tableSheetSpec so the rest of the
// file (buildSheetMatrix, sheetCreateDims, …) is unaware of it. Network-free:
// safe from Validate and DryRun.

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Remove everything after the final closing } or ] of the JSON value
  2. If you need multiple objects, wrap them in one array or one object instead of concatenating
  3. Re-quote the whole payload so the shell passes it as a single argument

Example fix

// before
--sheets '{"columns":[...]} {"extra":1}'
// after
--sheets '{"columns":[...]}'
Defensive patterns

Strategy: validation

Validate before calling

function assertSingleJSONValue(s) {
  const v = JSON.parse(s);
  const trimmed = s.trim();
  // re-serialize round-trip guards against trailing bytes after the value
  const probe = trimmed.replace(/^\s*[[{]/, m => m);
  JSON.parse(s + '');// syntax check
  if (countTopLevel(s) !== 1) throw new Error('trailing data after JSON value');
  return v;
}
function countTopLevel(s) { let d=0,n=0,inStr=false,esc=false; for(const c of s){ if(esc){esc=false;continue;} if(c==='\\'){esc=true;continue;} if(c==='"'){inStr=!inStr;continue;} if(inStr)continue; if(c==='{'||c==='[')d++; if(c==='}'||c===']'){d--; if(d===0)n++;}} return n; }

Type guard

function isCleanJSONObject(s) { try { JSON.parse(s); return /^\s*[\[{]/.test(s) && /\s*[\]}]\s*$/.test(s); } catch { return false; } }

Try / catch

try {
  await run(['lark','sheet','table-put','--sheets',payload]);
} catch (e) {
  if (/trailing data after JSON value/.test(e.message)) {
    payload = JSON.stringify(JSON.parse(payload.trim().replace(/^[\[{]/,'')));
    // simplest: rebuild payload via JSON.stringify from the parsed object
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing a --sheets/--values argument with extra characters after the closing brace/bracket, e.g. '{"columns":[]} extra' or two concatenated JSON objects '{..}{..}', or pasted content with a trailing comment.

Common situations: Pasting JSON from docs with a trailing sentence; concatenating two JSON blobs by mistake; shell appending an unquoted fragment; a stray comma-plus-object tail.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/4bc44eb5725a95b5. Report an issue: GitHub.