#include <bits/stdc++.h>
using namespace std;
int segtree[1000000];
void update(int idx, int val, int l, int r, int pos) {
  if (l > idx or r < idx) return;
  if (l == r) {
    segtree[pos] = val;
    return;
  }
  int mid = (l + r) >> 1;
  update(idx, val, l, mid, 2 * pos);
  update(idx, val, mid + 1, r, 2 * pos + 1);
  segtree[pos] = segtree[2 * pos] + segtree[2 * pos + 1];
}
int query(int lQ, int rQ, int l, int r, int pos) {
  if (l > rQ or r < lQ or l > r or lQ > rQ)
    return 0;
  else if (l >= lQ && r <= rQ)
    return segtree[pos];
  int mid = (l + r) >> 1;
  return query(lQ, rQ, l, mid, 2 * pos) +
         query(lQ, rQ, mid + 1, r, 2 * pos + 1);
}
const int maxn = 100010;
vector<int> graph[maxn];
vector<int> edgeId[maxn];
int depth[maxn];
int parent[20][maxn];
int lowerEnd[maxn];
int subtree[maxn];
void dfs(int u, int p, int d) {
  depth[u] = d;
  parent[0][u] = p;
  subtree[u] = 1;
  for (int i = 0; i < (int)graph[u].size(); i++) {
    int v = graph[u][i];
    int id = edgeId[u][i];
    if (v == p) continue;
    lowerEnd[id] = v;
    dfs(v, u, d + 1);
    subtree[u] += subtree[v];
  }
}
int lca(int u, int v) {
  if (u == v) return u;
  if (depth[u] > depth[v]) swap(u, v);
  int D = depth[v] - depth[u];
  for (int i = 19; i >= 0; i--)
    if (D & (1 << i)) v = parent[i][v];
  if (u == v) return u;
  for (int i = 19; i >= 0; i--)
    if (parent[i][u] != parent[i][v]) {
      u = parent[i][u];
      v = parent[i][v];
    }
  return parent[0][u];
}
int chainIdx[maxn];
int chainHead[maxn];
int posInTree[maxn];
int PTR = 1;
int currentChain = 0;
void hld(int u, int p) {
  if (chainHead[currentChain] == -1) chainHead[currentChain] = u;
  chainIdx[u] = currentChain;
  posInTree[u] = PTR++;
  int bigSize = 0, bigChild = -1;
  for (int v : graph[u]) {
    if (v == p) continue;
    if (subtree[v] > subtree[bigSize]) {
      bigSize = subtree[v];
      bigChild = v;
    }
  }
  if (bigChild != -1) hld(bigChild, u);
  for (int v : graph[u]) {
    if (v == p or v == bigChild) continue;
    currentChain += 1;
    hld(v, u);
  }
}
int queryUp(int node, int top) {
  int ret = 0;
  while (node != top) {
    if (chainIdx[node] != chainIdx[top]) {
      int hd = chainHead[chainIdx[node]];
      ret += query(posInTree[hd], posInTree[node], 1, PTR, 1);
      node = parent[0][hd];
    } else {
      ret += query(posInTree[top] + 1, posInTree[node], 1, PTR, 1);
      node = top;
    }
  }
  return ret;
}
void Q(int u, int v) {
  int L = lca(u, v);
  int ret = queryUp(u, L) + queryUp(v, L);
  if (ret > 0)
    printf("-1\n");
  else {
    int D = depth[u] - depth[L] + depth[v] - depth[L];
    printf("%d\n", D);
  }
}
void doit(int id, int val) {
  int v = lowerEnd[id];
  update(posInTree[v], val, 1, PTR, 1);
}
int main() {
  memset(chainHead, -1, sizeof(chainHead));
  int n;
  scanf("%d", &n);
  for (int i = 1; i < n; i++) {
    int u, v;
    scanf("%d", &u);
    scanf("%d", &v);
    graph[u].push_back(v);
    edgeId[u].push_back(i);
    graph[v].push_back(u);
    edgeId[v].push_back(i);
  }
  dfs(1, 0, 1);
  hld(1, 0);
  PTR -= 1;
  for (int i = 1; i < 20; i++)
    for (int j = 1; j <= n; j++)
      if (parent[i - 1][j] > 0) parent[i][j] = parent[i - 1][parent[i - 1][j]];
  int q;
  scanf("%d", &q);
  while (q--) {
    int type;
    scanf("%d", &type);
    if (type == 3) {
      int u, v;
      scanf("%d", &u);
      scanf("%d", &v);
      Q(u, v);
    } else {
      int e;
      scanf("%d", &e);
      type -= 1;
      doit(e, type);
    }
  }
  return 0;
}
